前言
在使用Jpa的时候,对几个实体类做了关联关系,在进行update操作时候,需要提交表单,除了封装一个相关属性的DTO之外,我们也可以这样子操作:
首先,对于jpa来时底层使用的hibernate的ORM框架,实体类和数据库中的表是做了映射的,那么在我们提交表单的时候,如果做了关联关系,我们提交具有外键的数据是无法提交的,如果我们相拥需要在实体类中定义一个只具有关联表的主键的构造函数。具体看代码:
实体类
// 这个是我们需要更新的实体,他关联了Teacher和Collections两张表, 并且属性中并没有teacherId和coll_id的属性,所以按照正常提交时无法提交的
@Entity
@Table(name = "students")
@Cacheable(true)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "entityCache")
@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler", "fieldHandler"})
public class Students {
private Integer stuId;
private String stuName;
private Integer stuAge;
private Integer stuSex;
private Date stuBirth;
private Collections collections;
private Teacher teacher;
@Id
@Column(name = "stu_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Integer getStuId() {
return stuId;
}
public void setStuId(Integer stuId) {
this.stuId = stuId;
}
@Column(name = "stu_name", length = 15)
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
@Column(name = "stu_age", length = 3)
public Integer getStuAge() {
return stuAge;
}
public void setStuAge(Integer stuAge) {
this.stuAge = stuAge;
}
@Column(name = "stu_sex", length = 1)
public Integer getStuSex() {
return stuSex;
}
public void setStuSex(Integer stuSex) {
this.stuSex = stuSex;
}
@Column(name = "stu_birth")
@Temporal(TemporalType.DATE)
public Date getStuBirth() {
return stuBirth;
}
public void setStuBirth(Date stuBirth) {
this.stuBirth = stuBirth;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "coll_id")
public Collections getCollections() {
return collections;
}
public void setCollections(Collections collections) {
this.collections = collections;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "teacher_id")
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
@Override
public String toString() {
return "Students => [" +
"stuId=" + stuId +
", stuName='" + stuName + '\'' +
", stuAge=" + stuAge +
", stuSex=" + stuSex +
", stuBirth=" + stuBirth +
", collections=" + collections +
", teacher=" + teacher +
']';
}
}
// 关联表Teacher,
// 我们在这个实体类中添加 默认构造函数和包含主键属性的一个构造函数
@Entity
@Table(name = "teacher")
@Cacheable(true)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "entityCache")
@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler", "fieldHandler"})
public class Teacher {
private Integer teacherId;
private String teacherName;
private Integer teacherSex;
private Set<Students> students;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "teacher_id")
public Integer getTeacherId() {
return teacherId;
}
public void setTeacherId(Integer teacherId) {
this.teacherId = teacherId;
}
@Column(name ="teacher_name", length = 15)
public String getTeacherName() {
return teacherName;
}
public void setTeacherName(String teacherName) {
this.teacherName = teacherName;
}
@Column(name = "teacher_sex", length = 1)
public Integer getTeacherSex() {
return teacherSex;
}
public void setTeacherSex(Integer teacherSex) {
this.teacherSex = teacherSex;
}
// 双向一对多的关联
@JsonIgnore
@OneToMany(targetEntity = Students.class)
@JoinColumn(name = "teacher_id")
public Set<Students> getStudents() {
return students;
}
public void setStudents(Set<Students> students) {
this.students = students;
}
// 默认
public Teacher() {
}
// 只包含teacherId
public Teacher(Integer teacherId) {
this.teacherId = teacherId;
}
// 包含全部
public Teacher(Integer teacherId, String teacherName, Integer teacherSex) {
this.teacherId = teacherId;
this.teacherName = teacherName;
this.teacherSex = teacherSex;
}
@Override
public String toString() {
return "Teacher => [" +
"teacherId=" + teacherId +
", teacherName='" + teacherName + '\'' +
", teacherSex=" + teacherSex +
']';
}
}
// Collections实体类
@Entity
@Table(name = "collections")
@Cacheable(true)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "entityCache")
@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler", "fieldHandler"})
public class Collections {
private Integer collId;
private String collName;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "coll_id")
public Integer getCollId() {
return collId;
}
public void setCollId(Integer collId) {
this.collId = collId;
}
@Column(name = "coll_name", length = 25)
public String getCollName() {
return collName;
}
public void setCollName(String collName) {
this.collName = collName;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Collections)) return false;
Collections that = (Collections) o;
return Objects.equals(getCollId(), that.getCollId()) &&
Objects.equals(getCollName(), that.getCollName());
}
@Override
public int hashCode() {
return Objects.hash(getCollId(), getCollName());
}
public Collections() {
}
public Collections(Integer collId) {
this.collId = collId;
}
public Collections(Integer collId, String collName) {
this.collId = collId;
this.collName = collName;
}
@Override
public String toString() {
return "Collections => [" +
"collId=" + collId +
", collName='" + collName + '\'' +
']';
}
}
前段的Ajax提交操作
// 编辑表单提交
function edit_sub(){
// 我们要提交的数据按如下格式封装
var data = {
"stuId": $("input[name='stuId']").val(),
"stuName": $("input[name='stuName']").val(),
"stuAge": $("input[name='stuAge']").val(),
"stuSex": $("input[name='stuSex']").val(),
"stuBirth": $("input[name='stuBirth']").val(),
"collections":{
"collId": $("#inputClass").val()
},
"teacher":{
"teacherId": $("#inputTeacher").val()
}
};
// 修改post请求头部
$.ajaxSettings.contentType = "application/json;charset=UTF-8";
$.post("/crud/stu/", JSON.stringify(data), function(res){
console.log(res);
if(res.code == 100){
$('#edit_model').modal('hide');
window.location.reload();
}
})
}
控制器
/**
* @function 编辑页面表单提交
* @param students
* @return
*/
@PostMapping("/stu")
@ResponseBody
// 在参数中需要加 @RequestBody 否则这或报错
public Msg edit_sub(@RequestBody Students students){
System.out.println("students : " + students);
studentsService.updateById(students);
return Msg.success();
}
Service层
@Override
public void updateById(Students students) {
// 调用JpaRepository中的save方法去更新
studentsRepository.save(students);
}
Repository
public interface StudentsRepository extends Repository<Students, Integer>, JpaRepository<Students, Integer> {
}
附加
CrudRepository中也有save方法,但是和JpaRepository中的save方法是实现是不一样的
CrudRepository中的save()
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);//是新的就插入
return entity;
} else {
return em.merge(entity); //不是新的merge
}
}
// CrudRepository 中的save方法是相当于merge+save ,它会先判断记录是否存在,如果存在则更新,不存在则插入记录
JpaRepository中的save()
@Transactional
public <S extends T> List<S> save(Iterable<S> entities) {
List<S> result = new ArrayList<S>();
if (entities == null) {
return result;
}
for (S entity : entities) {
result.add(save(entity));
}
return result;
}