`
andyhu1007
  • 浏览: 199491 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Hibernate中的cascade和inverse

阅读更多

这两个属性都用于一多对或者多对多的关系中。而inverse特别是用于双向关系,在单向关系中我们并不需要。

 

Cascade代表是否执行级联操作,Inverse代表是否由己方维护关系。

 

Cascade:

 

Cascade属性的可能值有

    all: 所有情况下均进行关联操作,即save-update和delete。
    none: 所有情况下均不进行关联操作。这是默认值。
    save-update: 在执行save/update/saveOrUpdate时进行关联操作。
    delete: 在执行delete 时进行关联操作。

    all-delete-orphan: 当一个节点在对象图中成为孤儿节点时,删除该节点。比如在一个一对多的关系中,Student包含多个book,当在对象关系中删除一个book时,此book即成为孤儿节点。

 

Inverse:

 

Inverse属性的可能值是true或者false,默认为false:

 

     false代表由己方来维护关系,true代表由对方来维护关系。在一个关系中,只能由一方来维护关系,否则会出问题(解疑中会讲到);同时也必须由一方来维护关系,否则会出现双方互相推卸责任,谁也不管。

 

一多对的例子:

 

有两个类,Father和Child,是一对多的关系。下面这段hbm配置是从Father.hbm.xml中摘取的。

 

 

<set name="children" lazy="true" cascade="all" inverse="true">
    <key column="fatherid"/>
    <one-to-many class="my.home.Child"/>
</set>  

 

我们知道cascade和inverse的值对会有四种组合的可能(在此仅先假定cascade值为none或all)。

 

有如下一段代码:

 

FatherDao fatherDao = new FatherDao();

Father father = new Father("David");
Child child1 = new Child("David Junior One");
Child child2 = new Child("David Junior Two");

father.add(child1);
father.add(child2);

fatherDao.save(father);

 

1. 如果cascade="all"且inverse="false"时:

 

此时可以看到log里面:

 

// 执行对father的插入
Hibernate: insert into father (name) values (?)

// cascade = 'all',所以进行级联操作
Hibernate: insert into child (name, fatherid) values (?, ?)
Hibernate: insert into child (name, fatherid) values (?, ?)

// inverse = 'false',由father来维护关系(可以看到这些操作是多余的)
Hibernate: update child set fatherid =? where ID=?
Hibernate: update child set fatherid =? where ID=?
 

2. 如果cascade = "none" 且 inverse = "false":

 

// 执行对father的插入
Hibernate: insert into father (name) values (?)

// inverse='false',所以更新关系
Hibernate: update child set fatherid =? where ID=?

// 但由于cascade='none',child并未插入数据库,导致如下exception
org.springframework.dao.InvalidDataAccessApiUsageException: object references an unsaved transient instance
 

3. 如果cascade = "all" 且 inverse = "true"

 

// 执行对father的插入
Hibernate: insert into father (name) values (?)

// cascade='all',执行对child的插入
Hibernate: insert into child (name, fatherid) values (?, ?)
Hibernate: insert into child (name, fatherid) values (?, ?)

// 但由于inverse='true',所以未有对关系的维护。但由于一对多的关系中,关系本身在“多”方的表中。所以,无需更新
关系。
 

4. 如果cascade = "none" 且 inverse = "true"

 

// 只执行对father的插入
Hibernate: insert into father (name) values (?)
 

可以看到,对于一对多关系,关系应由“多”方来维护(指定“一”方的inverse为true),并且应在“一”方指定相应的级联操作。

 

多对多:

 

在多对多关系中,inverse可以为任何一方,没有什么区别。

 

解疑:

 

为什么在多对多中不能由双方都来维护关系了:因为这样会导致重复更新中间表的可能,报出重复值的错误。

 

那么如何在多对多的双向关联中使双方都能维护关系:最好让控制关系的那方来更新关系,如果想让另一方也来维护关系,那么只有在操作这一方的数据时“显式”更新中间表了吧。

 

注意:

 

同时注意在双向关联中,对象之间的关联跟上面提及的关系表维护没有关系。一个是对象/java层面的,一个是hibernate数据库层面的。如果你想在更新一方时,也更新另一方的对象集合,请看下面这段代码:

 

这是Person类中的一段代码,Person和Event是多对多的双向关联关系,他们在对方类中的集合分别为participants和events。关系表由Person维护,所以对象关系的维护也在Person类中,而不是Event类中。

 

public void addToEvent(Event event) {
        this.getEvents().add(event);
        event.getParticipants().add(this);
}

public void removeFromEvent(Event event) {
        this.getEvents().remove(event);
        event.getParticipants().remove(this);
}
 
分享到:
评论
15 楼 liuhong2099 2009-09-17  
支持楼主,在来点Lazy 的吧,文档看的很累人的
14 楼 少女杀手 2009-06-13  
更上一层楼!
13 楼 zhangyou1010 2009-06-11  
再次看楼主的贴。
12 楼 diaolanshan 2009-03-09  
tinyyea 写道
wangneng_001 写道
谢谢iranger的解释。。。

不过这样all-delete-orphan好像就跟all没什么区别了。。。


hi.

session有套api用来update和delete,在改变了对象之后调用可以看到相应的更新或者删除语句。
但是在hibernate中,你不需要显示调用session.update或者delete,在改变了对象之后,直接拿到事务commit就能发现数据库状态也被改变了。
事实上,session.update和delete只是生成一条更新或者删除语句,最终都是清理缓存时才执行
实质上,删除或者不删除与生成的SQL语句有关,处于一个session的持久对象,在经历了一些逻辑之后,有些对象可能要被删除,它们被解除了关联关系,部分对象成了孤儿,但你并没有调用session.delete方法,所以删除这些对象的SQL就没有生成,而你的cascade=all,hibernate对比缓存状态,只是把外键更新成了null,当cascade=all-delete-orphan时情况完全不同,hibernate为那些孤儿对象生成删除语句,并很果断地执行了这些语句。始终注意一个前提:你没有显示地调用session.delete方法。
当你显示地调用了session.delete方法时,cascade=all或者all-delete-orphan就确实没有区别。

任何东西显示得写出来都容易明白,JPA里就没有类似all-delete-orphan的CascadeType


分析的很透彻,其实也就是说如果是all的话不进行对多的物理删除。
11 楼 hantsy 2009-03-09  
JPA 规范中没有orphan的含义,不知道其它jpa实现是如果如何处理的
10 楼 唯快不破 2009-03-07  
引用
Father和Child,是一对多的关系。

应该是child1.add(father);吧?
9 楼 tinyyea 2009-03-03  
wangneng_001 写道
谢谢iranger的解释。。。

不过这样all-delete-orphan好像就跟all没什么区别了。。。


hi.

session有套api用来update和delete,在改变了对象之后调用可以看到相应的更新或者删除语句。
但是在hibernate中,你不需要显示调用session.update或者delete,在改变了对象之后,直接拿到事务commit就能发现数据库状态也被改变了。
事实上,session.update和delete只是生成一条更新或者删除语句,最终都是清理缓存时才执行
实质上,删除或者不删除与生成的SQL语句有关,处于一个session的持久对象,在经历了一些逻辑之后,有些对象可能要被删除,它们被解除了关联关系,部分对象成了孤儿,但你并没有调用session.delete方法,所以删除这些对象的SQL就没有生成,而你的cascade=all,hibernate对比缓存状态,只是把外键更新成了null,当cascade=all-delete-orphan时情况完全不同,hibernate为那些孤儿对象生成删除语句,并很果断地执行了这些语句。始终注意一个前提:你没有显示地调用session.delete方法。
当你显示地调用了session.delete方法时,cascade=all或者all-delete-orphan就确实没有区别。

任何东西显示得写出来都容易明白,JPA里就没有类似all-delete-orphan的CascadeType
8 楼 tinyyea 2009-03-03  
wangneng_001 写道
all-delete-orphan: 当一个节点在对象图中成为孤儿节点时,删除该节点。比如在一个一对多的关系中,Student包含多个book,当在对象关系中删除一个book时,此book即成为孤儿节点。

这里还不太明白。。。


脱离与student的关系,
student.books.remove(book)
此时,它成了孤儿。即使程序没有book.setStudent(null),book也将被hibernate认为是孤儿,hibernate将删除之,并自动book.setStudent(null)。

单纯的只是book.student = null, hibernate不会认为book是孤儿。
在事务提交时,hibernate将更新数据库中book.student_id为null,如果数据库约束该字段不能为null,则抛出异常。
且即便是事务可以成功提交,student.books.contains(book)仍然成立!程序开始出现Bug 

BTW,当cascade=all-delete-orphan,无论inverse是true或false,以上结果仍成立,只是false的情况会多产生一条update。
这也再次验证cascade和inverse其实没有什么关系,经常把两个放一起讨论时常产生误导……
7 楼 winstonczc 2009-02-18  
呵呵,学习了
6 楼 iranger 2009-02-11  
不过这样all-delete-orphan好像就跟all没什么区别了。。。
________________________________________________________

当然有区别。
casacde属性设置为“all”,则包括了save-update和delete的行为
all-delete-orphan包括了all和delete-orphan的行为

你可以自己修改后看看Hibernate生成的sql语句就知道了
5 楼 wangneng_001 2009-02-10  
谢谢iranger的解释。。。

不过这样all-delete-orphan好像就跟all没什么区别了。。。
4 楼 iranger 2009-02-09  
“孤儿”是建立在父子关系基础上的,这里的父子关系不是指继承上的父子关系,而是指一个类的持久化生命周期必须由另外一个类来控制,即父方控制子方的持久化生命周期。我来举一个例子解释什么叫“孤儿”,

我现在有个类叫Item,还有个类叫Bid,Item指一个商品的条目,Bid为包含该条目的订单,在这里,我们规定order对象必须和一个item对象关联,脱离了item的order对象所代表的数据记录将被从数据库删除。设一个Item可以包含多个Bid,则在Item的POJO中,有如下这样一个集合:
private Set<Bid> bids = new HashSet<Bid>();

当然还有相应的获取器方法(即get/set)。
而在Bid类中,有个对Item的引用:
private Item item;

在Item的映射文件中,有如下一段
<set name="bids" cascade="all-delete-orphan" inverse="true">
           <key column="item_id"/>
           <one-to-many class="persistence.domain.parentAndChild.Bid"/>
</set>



当我们移除Item对象和一个Bid对象的关联关系后,即进行类似如下操作后
item.getBids.remove(order);
order.setItem(null);

这个特定的order就是一个孤儿了,明白了?
当我们执行上面操作时,Hibernate会执行类似下面的SQL语句:delete from bids where item_id=? and bid_id=?

另外,注意下面两点
当保存或者更新Item对象时候,级联保存相关联的Bid对象,相当于cascade属性为“save-update”
当删除Item对象时候,级联删除所有关联的Bid对象,相当于cascade属性为“delete”
呵呵,不知道说明白没有。
3 楼 wangneng_001 2009-02-06  
all-delete-orphan: 当一个节点在对象图中成为孤儿节点时,删除该节点。比如在一个一对多的关系中,Student包含多个book,当在对象关系中删除一个book时,此book即成为孤儿节点。

这里还不太明白。。。
2 楼 only_java 2009-01-13  
但实际应用中,会不会更多的是代码维护关联关系呢?
1 楼 only_java 2009-01-13  
不错,看明白了!

相关推荐

    Hibernate中cascade和inverse应用

    在 Hibernate 框架中,`cascade` 和 `inverse` 是两个重要的概念,它们主要用于管理对象之间的持久化关系,特别是涉及到一对一(one-to-one)、一对多(one-to-many)和多对多(many-to-many)关系时。这两个属性都...

    Hibernate中cascade与inverse属性详解

    Hibernate中cascade与inverse属性详解

    hibernate 级联(cascade和inverse)一对多

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

    hibernate inverse和cascade的详细讲解

    ### Hibernate Inverse 和 Cascade 的详细讲解 #### 一、引言 在ORM(Object-Relational Mapping)领域,Hibernate作为一款流行的Java持久层框架,它提供了丰富的API和配置选项来帮助开发者实现对象与数据库表之间...

    Hibernate中Inverse和Cascade的区别.html

    Hibernate中Inverse和Cascade的区别.html

    Hibernate_级联关系说明_-_关于cascade和inverse的用法

    在探讨Hibernate框架中的级联操作(cascade)与控制权反转(inverse)之前,我们需要先对Hibernate有一个基本的理解。Hibernate是一个开放源代码的对象关系映射(ORM)框架,它为Java应用提供了一种将对象模型映射到...

    关联映射cascade,inverse讲解

    本篇将深入讲解“cascade”和“inverse”这两个重要的概念,以及它们在实际应用中的作用。 首先,让我们理解一下“关联映射”。在Hibernate中,关联映射允许我们将Java对象与数据库表的记录进行关联。例如,一个...

    inverse和cascade使用阐述

    在IT领域,"inverse"和"cascade"是两个常见的概念,尤其在数据库设计、软件工程以及数据处理中。这两个术语通常与关系型数据库中的外键约束、对象关系映射(ORM)工具,以及某些编程框架的特性相关。下面将详细阐述这...

    关于cascade和inverse属性[文].pdf

    总结起来,`cascade`和`inverse`是Hibernate中用于管理对象关联关系的重要属性,它们共同确保了数据的一致性和操作的便捷性。在实际应用中,需要根据业务逻辑和性能需求,合理设置这两个属性,以达到最佳的数据库...

    hibernate集合映射inverse和cascade详解.txt

    `inverse`和`cascade`属性是Hibernate集合映射中非常重要的概念,它们帮助开发者更灵活地控制实体之间的关系以及操作的级联行为。合理地使用这两个属性,不仅可以简化代码,还能提高程序的性能和健壮性。然而,不当...

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

    ### Hibernate中的Cascade选项详解 #### 一、概述 在Hibernate框架中,cascade选项提供了一种管理实体间关联的便捷方式,使得对一个实体的操作能够自动地应用到与之相关的其他实体上。这对于处理复杂的数据库关系...

    JavaEE学习笔记之Hibernate表关系之一对多(inverse详解)

    `inverse`属性是Hibernate中用于控制关联维护权的重要参数,它的主要作用在于确定关联关系的更新和删除操作由哪一方负责。默认情况下,关联的维护权在"多"端,即子实体,这意味着当子实体发生变化时,如增加、删除或...

    Hibernate学习笔记和资料

    hibernate中一对一,一对多,多对多关系的配置,延迟加载,cascade,inverse hibernate查询方式概述,HQL查询,QBC查询,分页,结果集封装方式 ,高级查询 查询的优化,一级缓存,二级缓存,批量查询,注解方式

    Hibernate开发租房系统2 源码

    描述提到“使用cascade和inverse优化区和街道关联关系”,这意味着我们将深入理解Hibernate的cascade和inverse属性,以及它们在双向一对多关联关系中的应用。 Hibernate是Java领域中广泛使用的对象关系映射(ORM)...

    Hibenate cascade

    在Hibernate中,`cascade`和`inverse`是两个重要的概念,它们涉及到对象之间的关系管理和数据持久化。 **1. Hibernate Cascade** `cascade`属性主要用于控制对象间的级联操作。当在主对象上执行保存、更新、删除等...

    hibernate

    根据提供的文件信息,我们可以深入探讨Hibernate框架中的几个关键概念,特别是`fetch`, `lazy`, `cascade`, 和 `inverse`关键字的使用与理解。这四个概念在处理对象关系映射(ORM)时非常重要,尤其是在Java环境下...

    Hibernate常见问题

    理解并正确使用Hibernate的`cascade`和`inverse`属性对于优化数据操作和避免数据一致性问题至关重要。在实际开发中,应根据业务逻辑和数据模型谨慎设定这些属性,以确保数据操作的正确性和高效性。

    inverse 例子

    在Hibernate这个强大的对象关系映射(ORM)框架中,`inverse`属性是一个非常重要的概念,它主要用于管理关联关系的维护责任。在这个例子中,我们将会深入理解`inverse`属性的作用,并通过一个简单的测试案例——`...

Global site tag (gtag.js) - Google Analytics