Hibernate inverse介绍

inverse常用于一对多双向关联关系中。

以Student(学生)和ClassInfo(班级)为例,它们之间的关系为一对多的关系,即一个学生只能属于一个班级,一个班级可以包含多个学。

1. 类定于

Student类,省略get/set

package wen.hui.inverse; public class Student { private int id; private String name; private ClassInfo classInfo;

ClassInfo类,省略get/set

package wen.hui.inverse; import java.util.HashSet; import java.util.Set; public class ClassInfo { private int id; private String name; private Set students = new HashSet();

2. 配置文件.
Student.hbm.xml

<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="wen.hui.inverse.Student" table="inv_student"> <id name="id" type="int" column="ID"> <generator class="identity" /> </id> <property name="name" type="string" column="NAME" /> <many-to-one name="classInfo" column="CLASS_ID" class="wen.hui.inverse.ClassInfo" cascade="save-update" /> </class> </hibernate-mapping>

ClassInfo.hbm.xml

<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="wen.hui.inverse.ClassInfo" table="inv_classInfo"> <id name="id" type="int" column="ID"> <generator class="identity" /> </id> <property name="name" type="string" column="NAME" /> <set name="students" table="STUDENT" cascade="save-update" inverse="false"> <key column="CLASS_ID" /> <one-to-many class="wen.hui.inverse.Student" /> </set> </class> </hibernate-mapping>

此时在ClassInfo.hbm.xml中,inverse="false"

运行如下测试代码:

@Test public void testInverse() { Configuration cfg = new Configuration().configure(); SessionFactory sf = cfg.buildSessionFactory(); Session s = sf.openSession(); s.beginTransaction(); ClassInfo c1 = new ClassInfo(); c1.setName("一班"); Student s1 = new Student(); Student s2 = new Student(); s1.setName("John"); s2.setName("Tom"); c1.getStudents().add(s1); c1.getStudents().add(s2); s1.setClassInfo(c1); s2.setClassInfo(c1); //注释 s.save(c1); s.getTransaction().commit(); s.close(); }

发出的SQL语句如下:

Hibernate: insert into inv_classInfo (NAME) values (?) Hibernate: insert into inv_student (NAME, CLASS_ID) values (?, ?) Hibernate: insert into inv_student (NAME, CLASS_ID) values (?, ?) Hibernate: update inv_student set CLASS_ID=? where ID=? Hibernate: update inv_student set CLASS_ID=? where ID=?

上面的代码会使Hibernate执行五条SQL语句,其中前三条是insert插入语句,后两条是update更新语句。插入就不用说了,那么为什么还要有更新语句呢?这是因为Class类映射文件的<set>元素中指定了inverse="false",这就告之Hibernate:inv_student表与inv_classInfo表的主外键关系是由ClassInfo类来维护的。当执行save后,执行了三条insert语句,这三条语句中的后两条是插入到inv_student表的,它们的CLASS_ID字段是通过s1.getClass().getID()取出的,假如我将上面“注释”处修改为s2.setClass(c2);(c2是另一个Class对象,可能是持久化对象),这样,主外键关系不就乱了吗。为了保证主外键关系,Hibernate在这种情况下会再执行两条update语句来更改inv_student表中两个新插入记录的CLASS_ID字段,当然,这时CLASS_ID字段的取值是从c1对象中直接取得,而不再是s1.getClass().getID()方式了。

把ClassInfo.hbm.xml中的inverse属性改为true(inverse="true")

结果发出的SQL语句:

Hibernate: insert into inv_classInfo (NAME) values (?) Hibernate: insert into inv_student (NAME, CLASS_ID) values (?, ?) Hibernate: insert into inv_student (NAME, CLASS_ID) values (?, ?)

将ClassInfo类映射文件的<set>元素中的inverse属性修改为true后,这就是告诉Hibernate:ClassInfo类不维护主外键关系了,这个任务就交给了Student类。于是,我们再执行上面的代码,Hibernate就会只执行三条insert语句,而不会执行任何update语句。因为Hibernate会通过Student类的s1.getClass().getID()和s2.getClass().getID()来确定CLASS_ID字段的值。
故,为了节省数据库资源,省却不必要的update语句,我们一般建议在一对多双向关联关系中,将一方的inverse属性设置为true,即将主外键的关系交由多方来维护。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值