`

inverse和cascade使用阐述

阅读更多
  最近发现许多人谈到博客可以巩固和提高自己的学习.所以决定在此发表一些自己的看法.
这里我想谈下自己对inverse和cascade使用.使用Hibernate一段时间了.总觉得自己对cascade和inverse的只是一点认识.这里进行简单的测试总结:
我使用了Classes和Student这2个一对多的关系进行测试.使用的环境是Junit4和Hibernate3.2.IDE使用Eclipse.
下面是Class的xml配置:
<hibernate-mapping 
	package="com.entity">
	<class name="Classes" table="tb_class">
	<id name="id">
	<generator class="native"></generator>
	</id>
	<property name="number"></property>
<!-- 
	在这里进行关系的设置
	
	大写的部分inverse="true"表示 Classes 本身不维护表之间的关系!,而由想反的一方 student来维护, 
	
	cascade="all"表示 无论是update,insert ,delete 都保持几连关系 

	lazy="true"表示初始化课室的时候不会把所有的学生都从数据库中load进来。  
	 -->
	<set name="students" inverse="true" cascade="all" lazy="true">
	<key>
	<column name="class_id"></column>
	</key>
	<one-to-many class="Student"/>
	</set>
</class>


下面是测试的代码:
情况1:
 System.out.println("cascade='all' inverse='true'主控方为Student.多的那一方");
		Session session = sf.openSession();
		Classes classes = new Classes();
		classes.setNumber("s1");
		System.out.println("Class建立关系");
		Student student = new Student();
		classes.getStudents().add(student);
		session.save(classes);
		session.beginTransaction().commit();
		session.close();
		
		Session session1 = sf.openSession();
		classes.setNumber("s1");
		System.out.println("Student建立关系");
		Student student1 = new Student();
		student1.setClasses(classes);
		session1.save(student1);
		session1.beginTransaction().commit();


输出的结果为:
cascade='all' inverse='true'主控方为Student.多的那一方
Classes建立关系
Hibernate: insert into tb_class (number) values (?)
//数据库语句发出但是tb_student表中的数据没有与Classes建立关系.外键设置为空
//这里证明了如果学生维护关系的话.只往课室加学生的话使用session.save的话将不会
//保存学生.

Hibernate: insert into tb_student (name, class_id) values (?, ?)
Student建立关系
//只能在存在课室之后再添加学生才能形成学生和课室的关系
Hibernate: insert into tb_student (name, class_id) values (?, ?)

情况2:
System.out.println("cascade='all' inverse='false'主控方为Classes.一的那一方");
		Session session = sf.openSession();
		System.out.println("Classes建立关系");
		Classes classes = new Classes();
		classes.setNumber("s1");
		Student student = new Student();
		classes.getStudents().add(student);
		session.save(classes);
		session.beginTransaction().commit();
		
		System.out.println("Class存在情况下.Student建立关系");
		Session session1 = sf.openSession();
		Student student1 = new Student();
		student1.setClasses(classes);
		session1.save(student1);
		session1.beginTransaction().commit();
		
		System.out.println("Class不存在情况下Student建立关系");
		Session session2 = sf.openSession();
		Classes classes2 = new Classes();
		classes2.setNumber("s1");
		Student student2 = new Student();
		student2.setClasses(classes2);
		session2.save(student2);
		session2.beginTransaction().commit();

测试输出的结果为:

Classes建立关系
Hibernate: insert into tb_class (number) values (?)
Hibernate: insert into tb_student (name, class_id) values (?, ?)
//明显比原来多了一句.这里每次学生都需要更新教室的id这速度将会减慢.
//在教室中有学生的集合.它自己无法判断哪个学生已经指向自己了.只能再有这学生的时候
//将这个教室号赋予给它.所以在这个学生与课室这个场景下应该设置学生来维护这个关系.
//当学生需要进入这个教室的时候才进行选择这是可以减轻数据库的负担.(一般的场景下.一对多都是多的一方维护关系比较多.)

Hibernate: update tb_student set class_id=? where id=?
Class存在情况下.Student建立关系
Hibernate: insert into tb_student (name, class_id) values (?, ?)
Class不存在情况下Student建立关系
Hibernate: insert into tb_student (name, class_id) values (?, ?)
//学生无法进入这个教室而在这教室还没建成之前
org.hibernate.TranientObjectException

情况3:
System.out.println("cascade没有设置  inverse='false'主控方为Classes.一的那一方");
		System.out.println("Classes建立关系");
		Session session = sf.openSession();
		Classes classes = new Classes();
		classes.setNumber("s1");
		
		Student student = new Student();
		classes.getStudents().add(student);
		session.save(classes);
		session.beginTransaction().commit();

测试输出结果:

Hibernate: insert into tb_class (number) values (?)
Hibernate: update tb_student set stu_id=? where id=?
//从下面异常可以看到.inverse定义的是关系和对象的级联关系。教室这里负责与学生建
//立关系.但是这时候出现的情况是并不存在这个学生.那就肯定报错了.
//也可以看出cascade定义的是关系两端对象到对象的级联关系

org.hibernate.TranientObjectException:object references an unsaved
transient instance - save the transient instance before flushing: com.entity.Student


与情况2的对比可以看出
cascade:在对主控方操作时,级联发生。
inverse: 在flush时(commit会自动执行flush),对session中的所有set,hibernate判断每个set是否有变化,
对有变化的set执行相应的sql,执行之前,会有个判断:if( inverse == true ) return;

可以看出cascade在先,inverse在后。

情况4
System.out.println("cascade没有设置  inverse='true'主控方为Student.多的那一方");
		Session session = sf.openSession();
		Classes classes = new Classes();
		classes.setNumber("s1");
		
		Student student = new Student();
		classes.getStudents().add(student);
		session.save(classes);
		session.beginTransaction().commit();

测试输出结果:

//这里因为2个级联关系都不存在.所以只是普通的添加
Hibernate: insert into tb_class (number) values (?)

下面是我测试的源码.由于jar包比较大就只传代码
分享到:
评论

相关推荐

    hibernate 级联(cascade和inverse)一对多

    在Java的持久化框架Hibernate中,级联操作(Cascade)和反转(Inverse)是两个重要的概念,它们主要用于管理对象关系模型中的关联关系。在一对多的关系中,这些特性可以帮助简化数据操作,提高代码的可读性和维护性...

    inverse 例子

    在进行关联关系操作时,理解并合理使用`inverse`属性对于优化性能和保持数据一致性至关重要。在实际开发中,应根据业务需求和性能考虑来决定是否使用`inverse`以及如何设置。记住,良好的设计和合理的ORM配置是提高...

    hibernate_配置cascade_及all-delete-orphan.doc

    在使用Hibernate时,正确选择和配置cascade选项对于高效地管理和维护实体之间的关系至关重要。通过了解不同选项的特点和应用场景,开发人员可以更加灵活地应对各种业务需求,同时也能够有效地避免潜在的数据一致性...

    深入浅出Hibernate完整版

    此外,还讨论了unsaved-value、Inverse和Cascade等概念,以及延迟加载机制,这些都是理解Hibernate数据访问模式的关键。 #### 事务管理与锁机制 事务管理是任何数据库操作中不可或缺的一部分,文档不仅阐述了基于...

    Hibernate开发指南(原版书)

    - **数据访问**:讨论PO(Persistent Object)和VO(Value Object)的区别,以及unsaved-value属性的作用,深入解析Inverse和Cascade机制,解释延迟加载(Lazy Loading)的原理和应用场景。 - **事务管理**:分析...

    信号处理导论

    反滤波器(Inverse Filters)和稳定性问题(Stability)也是书中可能探讨的内容。 综上所述,《信号处理导论》一书系统地讲解了信号处理的诸多方面,从采样定理的基础知识到数字滤波器的设计,再到系统特性的分析和...

    夏昕-Hibernate+开发指南.pdf

    - **数据访问**:探讨了PO(Plain Old Java Object)和VO(Value Object)的区别,以及unsaved-value、Inverse和Cascade、延迟加载等概念。 - **事务管理**:介绍了基于JDBC和JTA的事务处理方法。 - **锁机制**:讲解...

    Hibernate的多对一和一对多操作实例

    本文将深入探讨Hibernate框架下“多对一”和“一对多”的关联关系,并通过一个具体示例来阐述其操作流程与实现细节。 ### Hibernate中的“多对一”和“一对多” 在数据库设计中,“多对一”(Many-to-One)和“一...

    NHibernate中对象关系类型

    本文将深入探讨NHibernate中的对象关系类型,通过简单的代码实例来阐述其核心概念。 1. 对象关系类型 在NHibernate中,对象关系类型主要涉及如何将数据库表与类进行映射,以便于在对象模型和关系数据库之间建立...

    hibernate_one2many_2.zip_Java编程_Java_

    以下是对这个主题的详细阐述: 1. **配置映射文件**:在传统的Hibernate映射方式中,我们需要创建两个XML映射文件,一个是主实体的映射文件,另一个是从属实体的映射文件。在主实体的映射文件中,我们会定义一个...

Global site tag (gtag.js) - Google Analytics