Hibernate Cascade和Inverse


一、Cascade级联存在的意义

在实际做项目的时候,经常会遇到表与表之间的关联操作,比如一个班级里面有多个学生,一个部门有多个职员,这是一对多的关系,还有例如一个主题有一个作者,这是一对一,等,这时候就必须涉及到表的关联操作。

二、一对多的单向关联

什么是单向关联呢?

比如一个班级里面有多个学生,班级表关联学生表,属于一对多,但是学生表并不关联班级表,这个就属于单向的关联。

 

只能从Classes找到Student,所以为单项关联
Class.hbm.xml中的配置:

<set name="students" cascade="all" inverse="false">
            <!-- 
                用来描述外键
                  column  外键的名称
                     在hibernate低层拼接sql语句的时候,要用到外键
             -->
            <key>
                <column name="cid"></column>
            </key>
            <!-- 
                classes类与Student类之间的关系
             -->
            <one-to-many class="cn.itcast.sh08.hibernate.domain.Student"/>
</set>

而在Student.hbm.xml中除了id和name属性以外没有有关Class的属性设置

三、通过班级级联保存学生

把Classes.hbm.xml的配置加上cascade="save-update"

public void testSaveClasses_Cascade_Save_Student(){
        Session session = sessionFactory.getCurrentSession();
        Transaction transaction = session.beginTransaction();

        Classes classes =  new Classes();
        classes.setName("java基础班");

        /**
         * 创建了一个set集合,往set集合中添加了3个学生
         */
        Set<Student> students =  new HashSet<Student>();
        Student student = new Student();
        student.setName("王三麻子");
        Student student2 = new Student();
        student2.setName("潘金莲");
        Student student3 = new Student();
        student3.setName("林志玲");
        students.add(student);
        students.add(student2);
        students.add(student3);

        //建立班级和学生之间的关联
        classes.setStudents(students);
        session.save(classes);
        transaction.commit();
}

上面代码说明: 
当执行session.flush()的时候,通过session.save(classess)使classes变成持久化状态的对象,这个时候hibernate内部会去检查Classes.hbm.xml文件中的set元素,查看set元素上是否标有cascade属性,如果cascade属性的值为”save-update”,所以在保存classes的时候,检查classes对象中的set属性,这个时候set对象中有3个student对象,并且这三个student对象的主键没有值,所以在保存classes的时候同时保存了student。

四、保存班级的同时更新学生

在保存班级的同时更新学生也是同样的,上面的不变,执行的流程改变的就是在检查Student的主键的值的时候发现是有值的,所以执行的是更新操作。

五、Cascade常用的属性

cascade常用属性包括:

  • save-update
  • delete
  • all

上面已经提到了在更新班级或者新增班级的时候这个属性是必要的,并且是save-update属性值,另外两个delete和all是干什么用的呢?

public void testDeleteClasses(){
        Session session = sessionFactory.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        Classes classes = (Classes)session.get(Classes.class,2L);
        session.delete(classes);
        transaction.commit();
}

上述代码是在cascade=“save-update”的情况下执行的,如果cascade=“delete”或者是delete就会在删除班级的时候删除关联的学生。

六、inverse属性

这个属性的值只有两种,true或者是false,默认的是true表示不维护属性,false表示维护属性,不维护属性的意思就是说在你删除班级的时候,就算cascade的属性值是delete,对应的学生是不会被删除的,因为关系不被维护,又比如说:

在新增学生的时候可以插入新的学生,但是学生没有对应的外键,也就是没有对应的班级,因为inverse不维护关系。

七、级联和维护关系的区别

cascade是对象与对象之间的关系 
inverse是对象与外键之间的关系,针对的是外键

总结

  • 只能通过班级联系到学生,不能通过学生联系到班级 
  • 如果涉及到关系操作,只能从班级出发维护关系 
  • 只要涉及到维护关系就会发出update语句 
  • 所有一对多,一的一方维护关系效率不高 
  • 级联操作:save-update all delete

八、一对多的双向关联

其实跟一对多的单向关联差不多,只要你充分理解了单向关联,就基本理解双向,就像打架的时候,只不过是一种是只能一个人打另一个人,双向的就是两个人可以互相打,增加的部分: 

总结

  • 一对多如果多的一方维护关系,不会发出update语句
  • 一般情况下,一对多,多的一方维护关系效率比较高
  • 在一般情况下,Classes.hbm.xml文件中的set元素中的inverse属性一般设置为true
  • 如果上述的配置的inverse设置为false,那么只要更新了关系,只要在代码端建立了Classes与Student之间的关系,session只要操作Classes,就会发出更新外键的sql语句,这样效率比较低