前提:
inverse:负责外键维护;
cascade:负责记录的添加删除修改;
基础:
Hibernate中的"inverse"属性只有两个值"true"和"false"。"true"表示将关系维护的权力交给对方,"false"表示不交出维护权力(默认值)。
Hibernate中的"cascade"-书面化的解释为"该属性会使我们在操作主对象时,同时Hibernate帮助我们完成从属对象相应的操作".
* none -- 所有情况下均不使用级联,这是默认值
* save-update -- 级联保存或更新[在执行save/update/saveOrUpdate时进行关联操作]
* delete -- 级联删除
* delete-orphan -- 孤儿删除.(注意:只能应用在一对多关系)
#* all -- 除了delete-orphan的所有情况.(包含save-update + delete )
* all-delete-orphan -- 包含了delete-orphan的所有情况.(包含save-update delete delete-orphan)
出现位置:
inverse:只能在set、list、map等几个标签中设置,像many-to-one这一类的标签都不能设置"inverse"这个属性值
cascade:一方或多方都可以.
经验之谈:
开发当中,最常见的是一对多关系<多对多会拆成两个一对多>,这两个属性大多数情况是在一方的映射文件当中配置[<set name="linkmans" inverse="true" cascade="all" lazy... fetch.... >]
代码展示:
Customer 与 Linkman 一对多
---
public class Customer { private Long cust_id; private String cust_name; ... private Set<Linkman> linkmans = new HashSet<Linkman>(); getter();setter();... }
映射文件
<hibernate-mapping> <class name="domain.Customer" table="cst_customer"> <id name="cust_id" column="cust_id"> <generator class="native"/> </id> <property name="cust_name" column="cust_name"/> ... <!-- 配置一方 --> <set name="linkmans" inverse="true" cascade="all" lazy="true" fetch="subselect" > <key column="lkm_cust_id"/> <one-to-many class="domain.Linkman" /> </set> </class> </hibernate-mapping>
-------
public class Linkman { private Long lkm_id; private String lkm_name; ... private Customer customer; getter();setter();... }
映射文件
<hibernate-mapping> <class name="domain.Linkman" table="cst_linkman"> <id name="lkm_id" column="lkm_id"> <generator class="native"/> </id> <property name="lkm_name" column="lkm_name"/> ... <!-- 先配置多方 name 当前JavaBean中的属性 class 属性的全路径 column 外键的字段 --> <many-to-one name="customer" class="domain.Customer" column="lkm_cust_id" /> </class> </hibernate-mapping>
----Junit测试代码
@Test public void run(){ Session session = HibernateUtils.getSession(); Transaction tr = session.beginTransaction(); Customer c1=new Customer(); c1.setCust_name("Jack"); Linkman l1=new Linkman(); l1.setLkm_name("Spider-Man"); c1.getLinkmans().add(l1); session.saveOrUpdate(l1); tr.commit(); }
- 结果 一方记录 多方记录 保存 多方外键为空
- 粗略解释:
表中记录的保存只和cascade有关系,多方外键字段值的更新只和inverse有关系;在一方配置cascade="all" ,意味着保存一方时会级联
保存多方表中的记录<外键更新与否取决于inverse>,inverse="true"意味着一方放弃外键维护,外键维护权交给多方,所以多方新增的
记录中,外键的值为空.加上代码[l1.setCustomer(c1);]外键有值.
- 相同测试代码,其它情况辨析:<没有加l1.setCustomer(c1);>
- 一方 inverse=false cascade=all------ 结果 一方记录 多方记录外键 全部保存
- 一方 inverse=true多方cascade=all------ 结果 一方记录 保存
***当保存多方对象时
@Test public void run2(){ Session session = HibernateUtils.getSession(); Transaction tr = session.beginTransaction(); Customer c1=new Customer(); c1.setCust_name("Jack"); Linkman l1=new Linkman(); l1.setLkm_name("Spider-Man"); session.saveOrUpdate(l1); tr.commit(); }
---一方 inverse=true多方cascade=all------ 结果 多方记录 保存 外键为空
@Test public void run2(){ Session session = HibernateUtils.getSession(); Transaction tr = session.beginTransaction(); Customer c1=new Customer(); c1.setCust_name("Jack"); Linkman l1=new Linkman(); l1.setLkm_name("Spider-Man"); l1.setCustomer(c1); session.saveOrUpdate(l1); tr.commit(); }
---一方 inverse=true多方cascade=all------ 结果 一方记录 多方记录外键 全部保存
对于多对多<在Stack Overflow上摘录的解释>:
In case of many-to-many relation through intermediary table; "Cascade" says whether a record will be created/updated in the child table. Whereas "Inverse" says whether a record will be created/updated in the intermediary table.
[注]:个人见解,不当之处欢迎指正.