[转]Hibernate中的cascade、inverse以及mappedBy总结
Posted on 2015-01-22 09:56 redcoatjk 阅读(398) 评论(0) 编辑 收藏 举报有时, 相关知识只有经过动手才能融会贯通. 只有总结才能印象深刻.
比如以下这篇blog总结的就很不错.
摘自http://blog.csdn.net/xiaozhubisheng/article/details/17021923
相关阅读: http://www.cnblogs.com/redcoatjk/p/4236445.html
学习hibernate时对级联关系的概念老是分不清楚,尤其是cascade、inverse以及mappedBy的作用。下面通过例子来简单说明。
准备工作
首先创建数据库,新建两张表:
教室表cr,字段如下
学生表student,字段如下:
教室与学生是一对多的关系。
然后新建项目,添加hibernate支持,由于inverse是hbm.xml配置文件中的属性,而mappedBy是注解中的属性,因此分开说明。
cascade属性
cascade用于指示级联关系,即两个实体间存在级联关系(一个类是另一个类中的属性)时,当保存、更新或删除一个实体时,是否对关联的实体做出相应操作(数据库操作),例如
1 <hibernate-mapping> 2 <class name="model.Cr" table="cr" catalog="hbmtest"> 3 <id name="id" type="integer"> 4 <column name="id" /> 5 <generator class="identity" /> 6 </id> 7 <property name="cname" type="string"> 8 <column name="cname" length="20" /> 9 </property> 10 <set name="students" inverse="true"> 11 <key> 12 <column name="crid" /> 13 </key> 14 <one-to-many class="model.Student" /> 15 </set> 16 </class> 17 </hibernate-mapping></SPAN>
上面是cr表的映射配置,执行如下测试代码
Session session = HibernateSessionFactory.getSession();
session.beginTransaction();
Student stu = new Student();
stu.setName("zhu");
Cr cr = new Cr();
cr.setCname("cname");
Set<Student> set = new
HashSet<Student>();
set.add(stu);
cr.setStudents(set);
stu.setCr(cr);
session.save(cr);
session.getTransaction().commit();
执行上面代码后,数据表cr中插入一行,而student表未变化。而将上面的配置改为
<SPAN style="FONT-SIZE: 18px"><set name="students" cascade=<SPAN style="FONT-SIZE: 18px">"all" </SPAN>inverse="true">后,执行上述代码则<SPAN style="FONT-SIZE: 18px">student表会有<SPAN style="FONT-SIZE: 18px">数据插入。 </SPAN></SPAN></SPAN>
inverse
inverse属性用于指示本方是否参与维护关系,设为true时不维护,设为false时维护。此处的关系是指关联两张表的
外键或者关系表字段。本属性一般设置于一对多关系中的一端,并且设置为false,因为若由一端负责维护,每次更新完一端数据,都会去寻找于一端有关系的多段表中的行,并更新其外键字段。而由多端维护时,由于一端对象是多端对象的属性字段,所以,每次更新多端后提交数据,都会自动更新该字段(若有更新时),这样比较方便。
<hibernate-mapping> <class name="model.Cr" table="cr" catalog="hbmtest"> <id name="id" type="integer"> <column name="id" /> <generator class="identity" /> </id> <property name="cname" type="string"> <column name="cname" length="20" /> </property> <set name="students" cascade="all" inverse="true"> <key> <column name="crid" /> </key> <one-to-many class="model.Student" /> </set> </class> </hibernate-mapping>
执行以下测试代码:
Session session = HibernateSessionFactory.getSession();
session.beginTransaction();
Student stu = new Student();
stu.setName("zhu");
Cr cr = new Cr();
cr.setCname("cname");
Set<Student> set = new HashSet<Student>();
set.add(stu);
cr.setStudents(set);
session.save(cr);
session.getTransaction().commit();
结果:
cr表
student表
由上图可以看出,由于cr不负责维护关系,所以插入一条cr数据后虽然在student插入一行,但其外键为null。当更改inverse为false或默认设置时,结果会更新student表的crid字段。
mappedBy
mappedBy属性用于注解中,作用与inverse类似,不过其值必须为多端对象中对应一端对象的成员变量名。当设置后,由多端维护关系,未设置时,hibernate会去寻找由student的id字段和cr的id字段组成的关系表,如果未建立该表会报错。为了避免报错并且由两端同时维护关系,可以在一端加上@JoinColumn(name="多端外键字段名"),这样作用就等同于inverse=false了。
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinColumn(name="crid") public Set<Student> getStudents() { return this.students; }
Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); Student stu = new Student(); stu.setName("zhu"); Cr cr = new Cr(); cr.setCname("cname"); Set<Student> set = new HashSet<Student>(); set.add(stu); cr.setStudents(set); session.save(cr); session.getTransaction().commit();
执行结果未两张表均插入一行,而且student表中的外键不为空。