hibernate中cascade属性与inverse属性概念详解

自己在学习hibernate的过程中,一直对cascade属性和inverse属性的概念模糊不清,可能很多初学者也会碰到类似情况,主要有以下几个问题:

1、cascade属性和inverse属性的作用是什么,即为什么要用他们?

2、在什么情况下使用他们?

3、如何使用他们?

对于hibernate的实体对象的配置,可能时常会用上它们,所以必须将其弄清楚明白,

于是自己通过网上查找资料以及编写实例进行了大量 测试后,解决问题。

inverse和cascade的比较

这两个属性本身互不影响,但起的作用有些类似,都能引发关系表的更新。


inverse:

在映射一对多关系时,设为false(默认false),一的一方会维护两者之间的关系,设为true后,一的一方不会维护两者之间的关系。四个字概括——关联更新

作用:不使用它时(即默认false),对一的一方的数据操作(增加、更新、删除),如果改动了 set 集合,为了维护与多的一方的关系,hibernate会额外增加一条update语句,更新多的一方相关联字段,这样就降低了执行效率,额外消耗了性能。

inverse=true的作用就是:不管一的一方做怎样的数据操作,都不会反映到另一方,不会触发相应的update操作。

配置范围:只能配置在one-to-many,many-to-many的set标签上,一对多映射中一的一方。

示例1:one-to-many时。

学生(Student)与班级(ClassInfo)的关系,学生多的一方,班级一的一方

班级映射文件 ClassInfo.hbm.xml 配置如下(默认的情况下):

<set name="students">
    <key column="classId"/>
    <one-to-many class="Student"/>
</set>
插入操作的代码:

		Student student = new Student();
		student.setName("张三");
			
		ClassInfo classInfo = new ClassInfo();
	    classInfo.setName("重点班");

	    classInfo.getStudents().add(student);  //此行代码表示,由班级一方主控操作
	    session.save(student);
	    session.save(classInfo);

生成sql语句:

Hibernate: 
    insert 
    into
        tb_student
        (name, cardId, classId, id) 
    values
        (?, ?, ?, ?)
Hibernate: 
    insert 
    into
        tb_classInfo
        (name, id) 
    values
        (?, ?)
Hibernate: 
    update
        tb_student 
    set
        classId=? 
    where
        id=?
由此可见:每增加一个学生,额外生成了一条update语句。

数据库中数据如下:

tb_classInfo:     id        name

                            1         重点班

tb_student:        id        name        classId

                            1         张三           1

如果将ClassInfo.hbm.xml 配置如下,其它不变:

<!-- 设置inverse为true -->
<set name="students" inverse="true">
    <key column="classId"/>
    <one-to-many class="Student"/>
</set>
执行同样插入操作后,

生成sql语句:

Hibernate: 
    insert 
    into
        tb_student
        (name, cardId, classId, id) 
    values
        (?, ?, ?, ?)
Hibernate: 
    insert 
    into
        tb_classInfo
        (name, id) 
    values
        (?, ?)
可见,无更新语句了。

数据库中数据如下:

tb_classInfo:     id        name

                            1         重点班

tb_student:        id        name        classId

                            1         张三           null

表tb_student中字段classId为空,说明对班级的插入操作,没有维护与其对应的学生的关系。

示例2:many-to-many时。

学生(Student)和所修课程(Course),多对多的关系

多对多的关系是,两者会维护一张中间表,tb_student_course,

此时,学生表和课程表相对于此中间表,都是一对多关系

Student.hbm.xml 配置如下:

        <set name="courses" table="tb_student_course" >
		<key column="studentId"/>
		<many-to-many class="Course" column="courseId"/>
	</set>
插入操作的代码:

	Student student = new Student();
	student.setName("李四");
		
	Course course = new Course();
	course.setName("外语");
		
	student.getCourses().add(course); //由学生主控插入操作
		
	session.save(course);
	session.save(student);
生成sql语句:
Hibernate: 
    insert 
    into
        tb_course
        (name, id) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        tb_student
        (name, cardId, classId, id) 
    values
        (?, ?, ?, ?)
Hibernate: 
    insert 
    into
        tb_student_course
        (studentId, courseId) 
    values
        (?, ?)
由此可见:每增加一个学生与课程信息,在往数据库中insert学生信息和课程信息后,

还会往它们维护的中间表tb_student_course中insert数据,此数据作用就是维护它们的关系。

数据库中数据如下:

tb_student:        id        name      

                            1         李四         

tb_course:         id        name

                            1         外语

tb_student_course:     studentId        courseId

                                         1                       1

如果将Student.hbm.xml 配置修改如下,其它不变:

        <!-- 设置inverse为true -->
        <set name="courses" table="tb_student_course" inverse="true" >
		<key column="studentId"/>
		<many-to-many class="Course" column="courseId"/>
	</set>

执行同样插入操作后,

生成sql语句:

Hibernate: 
    insert 
    into
        tb_course
        (name, id) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        tb_student
        (name, cardId, classId, id) 
    values
        (?, ?, ?, ?)
可见,只有两条insert语句。

数据库中数据如下:

tb_student:        id        name      

                            1         李四         

tb_course:         id        name

                            1         外语

tb_student_course:     studentId        courseId   

                                        此表无数据

由此可得出结论:

  1. 对于数据插入的操作,inverse决定是否把对 set 的改动反映到数据库中,即是否产生update语句。
  2. one-to-many下,对于数据更新和删除的操作,也同数据的插入操作一样(在此就不具体演示了),当inverse=false时(默认时),对 set 集合的改动会产生update语句去更新对应的多的一方的数据。当inverse=true时,对 set 集合的改动不会产生update语句去更新对应的多的一方的数据。即放弃维护两者关系的权利
  3. many-to-many时,其实也可看成是one-to-many的特殊形式,student和course共同维护一个中间表tb_student_course。student表或course表对中间tb_student_course来说,都是一对多的关系,所以不管是student还是course,改变 set ,只更新中间表的数据,不会影响另一方
  4. 建议,一对多的映射配置,一般不让一的一方维护关系,会损耗性能,让多的一方去维护。所以一的一方的配置属性inverse=true。 但多对多情况时,一定让inverse=false。                                          

删除操作示例:

 // 删除一个班级。
	// inverse=false时,先更新相关联的student表的外键classId设为null,再删此班级
	// inverse=true时,不会更新student表classId字段,直接删班级会由于两者的外键约束,无法删除,报异常。
	ClassInfo classInfo = (ClassInfo)session.get(ClassInfo.class, 1);		
	session.delete(classInfo);


cascade:

级联指的是当主控方执行操作时,关联对象(被动方)是否同步执行同一操作。

作用:一个对象的操作,可以因级联而触发跟它相关联的所有对象的操作,由此简化了代码。

配置范围:只有“关系标记”才有cascade属性:many-to-one,one-to-one ,any ,set(map, bag, idbag, list, array) ,one-to-many(many-to-many)

假设三个对象: student(学生)、classInfo(班级)、course(课程)

student(多)----------> classInfo(一)

student(多)----------> course(多)

当我执行保存学生对象操作时:

session.save(student)   级联决定是否执行:save_or_update(classInfo)、 save_or_update(course)

当我执行更新学生对象操作时:

session.update(student)   级联决定是否执行: save_or_update(classInfo) 、save_or_update(course) 

当我执行删除学生对象操作时:

session.delete(student)   级联决定是否执行: session.delete(classInfo) 、session.delete(course) 

注意:save或者update的主控操作因级联引发的关联操作可能为save,也可能为update,hibernate会根据关联对象是否已存在于数据库中而决定是save还是update。

建议:cascade,一般对many-to-one,many-to-many,constrained=true的one-to-one 不设置级联删除

在many-to-many下,cascade影响到的是另一方,而inverse影响的是中间表。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值