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);

猜你喜欢

转载自garyjiao.iteye.com/blog/2242767