Hibernate 之 cascade 和 inverse
来源:互联网 发布:淘宝正道体育 编辑:程序博客网 时间:2024/05/27 12:21
1、Inverse在一对多关系和多对多关系中被声明使用(在多对一中没有inverse关键字) 理解关键字:关系
"inverse",应该改成“relationship owner"吗?
在hibernate,只有“关系的拥有者”才能维护两个实体类之间的关联关系(一对多或多对多)。“inverse”关键字创建的目的是指明哪一边(实体类)是关系的拥有者。 然而“inverse”关键字生涩难懂,建议改为“relationship_owner”
总之,inverse=“true”说明当前配置文件对应的实体类不是关系的拥有者,而其对应的关联实体类是关系的拥有者(也就是inverse属性所在元素对应的集合变量引用的实体类为关系的拥有者),反之相反。
2、cascade属性的作用是描述关联对象进行操作时的级联特性。因此,只有涉及到关系的元素才有cascade属性。 理解关键字:级联
3、上示例代码:
背景描述:城市、学校、学生三个对象;全部是1对多的关系;即
TestCity.java
package com.test;import java.util.HashSet;import java.util.Set;/** * 测试-城市 * Created by zmf on 16/4/13. */public class TestCity { private int id; private String name; private Set<TestSchool> schoolSet = new HashSet<TestSchool>(); public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<TestSchool> getSchoolSet() { return schoolSet; } public void setSchoolSet(Set<TestSchool> schoolSet) { this.schoolSet = schoolSet; }}
TestSchool.java
package com.test;import java.util.HashSet;import java.util.Set;/** * 测试-学校 * Created by zmf on 16/4/13. */public class TestSchool { private int id; private String name; private Set<TestStudent> students = new HashSet<TestStudent>(); private TestCity city; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<TestStudent> getStudents() { return students; } public void setStudents(Set<TestStudent> students) { this.students = students; } public TestCity getCity() { return city; } public void setCity(TestCity city) { this.city = city; }}
TestStudent.java
package com.test;import java.util.HashSet;/** * 测试-学生 * Created by zmf on 16/4/13. */public class TestStudent { private int id; private String name; private TestSchool school; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public TestSchool getSchool() { return school; } public void setSchool(TestSchool school) { this.school = school; }}
映射文件:
TestCity.hbm.xml
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><!-- Mapping file autogenerated by MyEclipse - Hibernate Tools--><hibernate-mapping> <class name="com.test.TestCity"><id name="id"> <generator class="identity" /> </id><property name="name"/><set name="schoolSet"><key column="city_id"></key><one-to-many class="com.test.TestSchool"></one-to-many></set> </class></hibernate-mapping>
TestSchool.hbm.xml
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><!-- Mapping file autogenerated by MyEclipse - Hibernate Tools--><hibernate-mapping> <class name="com.test.TestSchool"><id name="id"> <generator class="identity" /> </id><property name="name"/><many-to-one name="city" column="city_id" class="com.test.TestCity"></many-to-one><set name="students"><key column="school_id"></key><one-to-many class="com.test.TestStudent"></one-to-many></set> </class></hibernate-mapping>
TestStudent.hbm.xml
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><!-- Mapping file autogenerated by MyEclipse - Hibernate Tools--><hibernate-mapping> <class name="com.test.TestStudent"><id name="id"> <generator class="identity" /> </id><property name="name"/><many-to-one name="school" column="school_id" class="com.test.TestSchool"></many-to-one> </class></hibernate-mapping>
测试代码
package com.test;import com.util.HibernateSessionFactory;public class TestInverseAndCascade {public static void main(String[] args) {//testInverse_false();//两种删除方式TestCity city = (TestCity) HibernateSessionFactory.get(TestCity.class, 21);//TestCity city = new TestCity();//city.setId(19);////这时,city中的集合为空,则不会删除集合中的对象;HibernateSessionFactory.delete(city);}/** * 测试inverse属性为false时的关系维护,以及SQL的执行; 默认为false. */public static void testInverse_false () {TestCity city = new TestCity();city.setName("北京");TestSchool school = new TestSchool();school.setName("北京一中");TestStudent student1 = new TestStudent();student1.setName("张三");TestStudent student2 = new TestStudent();student2.setName("李四");//在主控方来设置关联关系//城市和学校city.getSchoolSet().add(school);//学校和学生school.getStudents().add(student1);school.getStudents().add(student2);//只处理城市HibernateSessionFactory.add(city);/*1 / 没有设置cascade时,sql如下,且报错Hibernate: insert into TestCity (name) values (?)Hibernate: update TestSchool set city_id=? where id=?由此可见,inverse只是负责维护之间的关系,并不负责处理save/update/delete关联对象(由cascade控制)此处有2个解决办法,第一个是在主控方来设置cascade;第二种是自己保存城市和学生,然后由inverse来控制关系第一种办法,先设置cascade为all,所有情况下均执行;cascade属性可选值:all : 所有情况下均进行关联操作。none:所有情况下均不进行关联操作。(默认值)save-update:在执行save/update/saveOrUpdate时进行关联操作。delete:在执行delete时进行关联操作。设置好,执行;Hibernate: insert into TestCity (name) values (?)Hibernate: insert into TestSchool (name, city_id) values (?, ?)Hibernate: update TestSchool set city_id=? where id=?Hibernate: update TestStudent set school_id=? where id=? //学校的学生set节点也要加设置好,执行:Hibernate: insert into TestCity (name) values (?)Hibernate: insert into TestSchool (name, city_id) values (?, ?)Hibernate: insert into TestStudent (name, school_id) values (?, ?)Hibernate: insert into TestStudent (name, school_id) values (?, ?)Hibernate: update TestSchool set city_id=? where id=?Hibernate: update TestStudent set school_id=? where id=?Hibernate: update TestStudent set school_id=? where id=?**cascade级联先发生,最后hibernate会根据inverse来判断是否来控制关联关系!**cascade用于触发增删改的级联操作,inverse来控制关联关系;设计时,要根据实际情况:1/城市的建立,不一定要建学校;2/学校建的时候会选择在哪个城市来建校,所以关系应该由学校控制;所以城市的set集合inverse应该设置为true;3/城市更名时,和学校的属性没有多大关系,房间和学生也不会更改任何属性.4/一旦城市被炸毁,则学校也一同死掉,但学生很可能因为事先逃亡了,所以没有死,只是不上学了.因此城市中的set节点应该是<set name="schoolSet" cascade="delete" inverse="true"><key column="city_id"></key><one-to-many class="com.test.TestSchool"></one-to-many></set>学校中,多对一的城市节点,应该是 cascade=none, 即学校改名/被拆,和城市没有关系,不用级联操作;<many-to-one name="city" column="city_id" cascade="none" class="com.test.TestCity" lazy="false"></many-to-one>学校中的学生,同理,建校时,没有学生,学校被拆和学生没有关系;学生上学和学校有关系,学生改名或者死掉不会影响学校<set name="students" inverse="true" cascade="none"><key column="school_id"></key><one-to-many class="com.test.TestStudent"></one-to-many></set>学生中的学校<many-to-one name="school" column="school_id" class="com.test.TestSchool" cascade="none" lazy="false"></many-to-one>**所以inverse 90%以上是由many来控制的,也是默认的.在one的一方,set标签中设置inverse=true.cascade 90%不用设置是(默认值none).即一方改名和删除和另一方没有关系.如果像城市/学校这样,城市被毁,则学校被毁,就设置delete.同样要设置delete的有 订单-订单明细; 用户-消费记录/登录记录;以上的代码要改成TestCity city = new TestCity();city.setName("北京");//创建城市,和玩游戏一样HibernateSessionFactory.add(city);//创建学校TestSchool school = new TestSchool();school.setName("北京一中");//设置关系school.setCity(city);HibernateSessionFactory.add(school);//学生出生TestStudent student1 = new TestStudent();student1.setName("张三");HibernateSessionFactory.add(student1);TestStudent student2 = new TestStudent();student2.setName("李四");HibernateSessionFactory.add(student2);//学生1去上学student1.setSchool(school);HibernateSessionFactory.update(student1);//学生2去上学student2.setSchool(school);HibernateSessionFactory.update(student2);Hibernate: insert into TestCity (name) values (?)Hibernate: insert into TestSchool (name, city_id) values (?, ?)Hibernate: insert into TestStudent (name, school_id) values (?, ?)Hibernate: insert into TestStudent (name, school_id) values (?, ?)Hibernate: update TestStudent set name=?, school_id=? where id=?Hibernate: update TestStudent set name=?, school_id=? where id=?考虑对象关系时,考虑2点:1/我的属性值改变或者我的存在消失,是否影响你的状态和你的消失,如果有影响则有cascade;2/我们的关系,是你管理好,还是我管理好.如果你关系好,则设置inverse=true;many一方没有这个属性;*/}/*sql脚本delete testSchool;DELETE testCity;DELETE testStudent;DECLARE @school_id int;INSERT INTO testCity (name) VALUES ('北京');INSERT INTO testSchool (name,city_id) VALUES ('北京一中', @@identity);SET @school_id= @@identity;INSERT INTO testStudent (name,school_id) VALUES ('张三', @school_id);INSERT INTO testStudent (name,school_id) VALUES ('李四', @school_id);SELECT * from testCitySELECT * from testSchoolSELECT * from testStudent */}
0 0
- Hibernate 之 cascade 和 inverse
- 【Hibernate】inverse和cascade
- Hibernate之inverse和cascade详解
- Hibernate之cascade属性和inverse属性
- Hibernate中Cascade和Inverse
- hibernate 的cascade和inverse
- Hibernate 的 Inverse 和 cascade
- Hibernate中cascade和inverse
- hibernate inverse 和cascade讲解
- Hibernate中cascade和inverse
- Hibernate中的cascade和inverse
- Hibernate中的cascade和inverse
- Hibernate cascade和inverse详解
- hibernate 中cascade 和inverse
- Hibernate中的cascade和inverse
- Hibernate(Inverse和Cascade属性)
- Hibernate中Cascade和Inverse
- Hibernate中的cascade和inverse
- 依赖倒置原则
- 用Canvas画带动画的渐变数字圆环
- windows10刻录并在新硬盘安装Fedora25
- ListView 卡顿的原因
- 面向对象方式解决比赛名单类问题(Java实现)
- Hibernate 之 cascade 和 inverse
- 第七周项目(1)-友员函数求两点间距离
- View绘制尚未完成,getHeight=0
- 解决android studio模拟器“is currently running"的方法
- 【kd-tree】BZOJ4520 CQOI2016K远点对
- listview的定位
- Android判断app是否后台运行中,后台运行通知栏提示
- iOS隐藏一个View(定时器)
- 【重来】【vip】5. Longest Palindromic Substring【m】【30】【97】