`

cascade和inverse

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

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

cascade:
cascade的属性有:
1·all:所有操作情况下都进行级联操作,即save-update和delete
2·none:所有情况下均不进行级联操作。这是默认值。
3·save-update:执行save/update/saveOrUpdate时进行级联操作。
4·delete:在执行delete操作的时候进行级联操作。
5·all-delete-orphan:当一个对象节点在对象图中成为孤儿节点时,删除该节点。比如在一个一对多的关系中,student包含多个book,当在对象关系中删除一个book时,此book即成为孤儿节点。



Inverse:

inverse属性值true或者false,默认值false(即默认己方维护关联关系)

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

domain对象:
import java.util.HashSet;
import java.util.Set;

public class Father {
	
	private Integer id;
	private String name;
	private Set<Child> children = new HashSet<Child>();
	
	public Father(){}
	
	public Father(String name){
		this.name = name;
	}
	
	public void addChild(Child child){
		if (!this.children.contains(child)) {
			this.children.add(child);			
		}
	}
	
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Set<Child> getChildren() {
		return children;
	}
	public void setChildren(Set<Child> children) {
		this.children = children;
	}
	
	

}


public class Child {

	private Integer id;
	private String name;
	private Father father;
	
	public Child(){}
	
	public Child(String name){
		this.name = name;
	}
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Father getFather() {
		return father;
	}
	public void setFather(Father father) {
		this.father = father;
	}
	
	
}


映射文件:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.itcast.hibernate.domain.inversecascade">

	<class name="Father" table="father">
		<id name="id" unsaved-value="-1">
			<generator class="native" />
		</id>
		<property name="name"/>
		<!-- cascade="all"且inverse="false" -->
		<set name="children" cascade="all" inverse="false">
			<key column="fatherid"/>
			<one-to-many class="Child"/>
		</set>
		
	</class>
</hibernate-mapping>



<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.itcast.hibernate.domain.inversecascade">

	<class name="Child" table="child">
		<id name="id" unsaved-value="-1">
			<generator class="native" />
		</id>
		<property name="name"/>
		<many-to-one name="father" column="fatherid"/>
	</class>
</hibernate-mapping>



如果cascade取值分为 all 和 none ; inverse取值分为 false 和 true,这两种情况,那么应该有四种组合。
cascade = all,inverse = false
cascade = all,inverse = true
cascade = none,inverse = false
cascade = none,inverse = true

下面分别测试:

1·cascade = all,inverse = false


测试代码:
	public static void main(String[] args) {
		Session session = HibernateUtil.getSession();
		Transaction tx = session.beginTransaction();
		
		Father father = new Father("father");
		Child child1 = new Child("child 1");
		Child child2 = new Child("child 2");
		
		father.addChild(child1);
		father.addChild(child2);
		
		session.save(father);
		
		tx.commit();
		session.close();
		
	}


执行的sql语句:

Hibernate: insert into father (name) values (?)
Hibernate: insert into child (name, fatherid) values (?, ?)
Hibernate: insert into child (name, fatherid) values (?, ?)
Hibernate: update child set fatherid=? where id=?
Hibernate: update child set fatherid=? where id=?




2·  cascade = all,inverse = true

		<!-- cascade="all"且inverse="true" -->
		<set name="children" cascade="all" inverse="true">
			<key column="fatherid"/>
			<one-to-many class="Child"/>
		</set>



执行的sql语句:
Hibernate: insert into father (name) values (?)
Hibernate: insert into child (name, fatherid) values (?, ?)
Hibernate: insert into child (name, fatherid) values (?, ?)


也就是说Child的对象的外键为空了!!

当然此时如果测试代码改成如下方式:

	public static void main(String[] args) {
		Session session = HibernateUtil.getSession();
		Transaction tx = session.beginTransaction();
		
		Father father = new Father("father");
		Child child1 = new Child("child 1");
		child1.setFather(father);
		Child child2 = new Child("child 2");
		child2.setFather(father);
		
		father.addChild(child1);
		father.addChild(child2);
		
		session.save(father);
		
		tx.commit();
		session.close();
		
	}


执行的sql语句为

Hibernate: insert into father (name) values (?)
Hibernate: insert into child (name, fatherid) values (?, ?)
Hibernate: insert into child (name, fatherid) values (?, ?)


但是数据库中的数据都是完整的了!!!


3·cascade = none,inverse = false

		<!-- cascade="none"且inverse="false" -->
		<set name="children" cascade="none" inverse="false">
			<key column="fatherid"/>
			<one-to-many class="Child"/>
		</set>


执行的sql语句

Hibernate: insert into father (name) values (?)
Hibernate: update child set fatherid=? where id=?
Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing:


级联取消,所以没有同时保存child,这时及时去跟新child的外键,只能出错了


4·cascade = none,inverse = true

		<!-- cascade="none"且inverse="true" -->
		<set name="children" cascade="none" inverse="true">
			<key column="fatherid"/>
			<one-to-many class="Child"/>
		</set>


执行的sql语句

Hibernate: insert into father (name) values (?)



cascade=none,没有级联保存child,所以child表中没有数据;inverse=true,放弃维护关联关系,所以没有去跟新child的外键,所以就不会报异常



多对多:



在多对多关系中,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);   
}



分享到:
评论

相关推荐

    Hibernate中cascade和inverse应用

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

    hibernate 级联(cascade和inverse)一对多

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

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

    在软件网络技术领域,尤其是在使用Hibernate这种对象关系映射(ORM)框架时,理解和正确使用`cascade`和`inverse`属性至关重要。这两个属性主要用于管理对象之间的关联关系,特别是如何在数据库中维护这些关系。 ...

    关联映射cascade,inverse讲解

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

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

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

    inverse和cascade使用阐述

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

    Hibernate中cascade与inverse属性详解

    Hibernate中cascade与inverse属性详解

    Hibernate中cascade与inverse属性详解.doc

    在Hibernate中,`cascade`和`inverse`是两个非常重要的属性,它们主要涉及到对象关系映射(ORM)中的数据同步和关联管理。首先,我们来分别解析这两个属性的含义和作用。 `cascade`属性用于控制当操作一个实体(如...

    Hibenate cascade

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

    hibernate inverse和cascade的详细讲解

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

    NHibernate Inverse & Cascade

    "NHibernate Inverse & Cascade"是两个关键概念,对于理解和有效使用NHibernate至关重要。 **Inverse属性** Inverse属性主要用于控制NHibernate如何处理关联对象的持久化。在一对多或多对一的关系中,当一个实体...

    Hibernate开发租房系统2 源码

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

    Hibernate常见问题

    3. **cascade和inverse的区别**:`cascade`关注的是对象之间的操作传递,而`inverse`关注的是关系的维护。`cascade`决定了一个对象的变更是否会影响到其他关联对象,`inverse`则决定了关系的维护责任在哪个对象。 4...

    Hibernate中Inverse和Cascade的区别.html

    Hibernate中Inverse和Cascade的区别.html

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

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

    inverse 例子

    首先,`inverse`属性主要应用于一对多(OneToMany)和多对一(ManyToOne)的关系映射中。默认情况下,Hibernate假设一方(通常是一对多的那一方)负责维护关联关系,也就是说,当这一方的对象被保存或更新时,它会...

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

    同时,确保理解`inverse`和`cascade`的组合使用,以防止意外的数据修改。 综上所述,理解并正确使用Hibernate中的`inverse`属性对于优化JavaEE应用的数据库操作和提高代码质量具有重要意义。通过深入掌握这一特性,...

    inverse=true的总结

    6. 工具应用:在实际开发中,理解并正确使用`inverse=true`能够提高代码的可维护性和性能。开发者应根据业务需求,谨慎选择关联的维护方,并合理配置级联操作,以达到最佳的数据操作效果。 总结,`inverse=true`是...

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

    &lt;set name="orders" cascade="all-delete-orphan" inverse="true"&gt; ``` 这样,在运行时会执行: ```sql DELETE FROM ORDERS WHERE CUSTOMER_ID = 2 AND ID = 2; ``` #### 四、总结 在使用Hibernate时...

Global site tag (gtag.js) - Google Analytics