Hibernate的级联操作问题
今天讲的是其实是一个老生常谈的问题,但这前一直没有完全搞清楚,今天正好项目里遇到相关问题,仔细弄了一会儿,终于算是搞明白了。
不知道大家有没有遇到过这个问题,举例先:
@Entity
public class Teacher {
private String name;
private Set<Student> students;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "teacher_oid")
public Set<Student> getStudents() {
return students;
}
//其他代码省略.......
}
@Entity
public class Student {
private String name;
}
在以上的例子里, 如果保存teacher时,students里有记录,那么Hibernate会自动保存Teacher和Student的记录,但问题在于,控制台可能会生成以下几句SQL:
insert into teacher(name, id) values ("T1", 1);
insert into student(name, id) values("S1", 1);
update student set teacher_oid = 1 where id = 1;
请留意以上第3句SQL,是不是觉得很多余,为什么第二句SQL里不能带着teacher_oid一起呢?
这里回到主题,今天要讲的就是Hibernate的inverse的事,通过对inverse的配置,就可以去掉第3句SQL,用2句SQL完成操作。
题外话:在Hibernate4里面,我们主要都是在annotation去实现,很少使用hbm.xml配置文件,那么之前很多文档里提到的那个inverse在注解方式该如何使用呢。其实就是使用mappedBy来完成的。
将之前的代码改成:
@Entity
public class Teacher {
private String name;
private Set<Student> students;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "teacher")
//不需要这行了 @JoinColumn(name = "teacher_oid")
public Set<Student> getStudents() {
return students;
}
//其他代码省略.......
}
@Entity
public class Student {
private String name;
//需要定义Teacher的引用
private Teacher teacher;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "teacher_oid")
public Teacher getTeacher() {
}
}
也就是OneToMany端配置mappedBy,然后ManyToOne端必须配置One那端的对象,这么改动之后,优点是Hibernate生成的SQL更简洁了,但缺点也很明显,之前子类不需要关注父类,但现在这样,子类必须拥有父类的引用。
生成的SQL如下:
insert into teacher(name, id) values ("T1", 1);
insert into student(name, id, teacher_oid) values("S1", 1, 1);
至于项目中如何选择,就看各位的想法了。
另外,在OneToMany里有一个orphanRemoval的配置,默认为false,也就是在级联操作的情况,如果子类的记录发生删除操作,Hibernate只会将那些被删除的子类记录的外键ID设为Null,但不会删除记录。
如果设为true,则Hibernate会将那些子记录一并删除。
但在操作上需要注意,要按照以下方式:
Teacher teacher = service.findById(1);
//不要直接调用teacher.setStudnets,而是需要先clear,再addAll
teacher.getStudents().clear();
teacher.getStudents().addAll(newStudentsList);
上一篇: 搜狗输入法i换肤该怎么关闭?
下一篇: 搜狗地图怎么注册?搜狗地图的使用方法
推荐阅读
-
约瑟夫环问题的PHP实现 使用PHP数组内部指针操作函数
-
关于angularjs异步操作后台请求时,用$q.all排列先后顺序的问题
-
SQL Server 数据库调整表中列的顺序操作方法及遇到问题
-
oracle数据库查询没问题,正常显示两个汉字;但是java后台Hibernate查询的时候只显示第一个汉字怎么解决?
-
Postgresql在mybatis中报错:操作符不存在:character varying == unknown的问题
-
解决在Linux操作系统下无法连接MySQL服务端的问题
-
解决vue页面DOM操作不生效的问题
-
详解Hibernate cascade级联属性的CascadeType的用法
-
C++操作MYSQL遇到的一些问题
-
文件无法删除/需要权限执行此操作/无法访问等问题的简单解决方法