hibernate配置文件中有这么一个属性inverse,它是用来指定关联的控制方的。
inverse属性默认是false,若为false,则关联由本身控制,若为true,则关联
由对方控制。
见例子:java
一个Parent有多个Child,一个Child只能有一个Parent。数据库
package com.xian;session
public class Child {
private Long id;
private String name;
private Parent parent;app
public Long getId() {
return id;
}post
public void setId(Long id) {
this.id = id;
}this
public String getName() {
return name;
}spa
public void setName(String name) {
this.name = name;
}.net
public Parent getParent() {
return parent;
}hibernate
public void setParent(Parent parent) {
this.parent = parent;
}xml
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
<class name="com.xian.Child" table="child">
<id name="id" column="childId">
<generator class="native" />
</id>
<property name="name" type="string"></property>
<many-to-one name="parent" column="parentId" not-null="true">
</many-to-one>
</class>
</hibernate-mapping>
package com.xian;
import java.util.HashSet;
import java.util.Set;
public class Parent {
private Long id;
private String name;
private Set children = new HashSet();
public Long getId() {
return id;
}
private void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set getChildren() {
return children;
}
public void setChildren(Set children) {
this.children = children;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
<class name="com.xian.Parent" table="parent">
<id name="id" column="parentId">
<generator class="native"></generator>
</id>
<property name="name" type="string"></property>
<set name="children" inverse="true">
<!-- 此处inverse设置为true,则关联的控制方交给了child,一对多关联通常都将控制方交给多端 -->
<key column="parentId" not-null="true"></key>
<one-to-many class="com.xian.Child"/>
</set>
</class>
</hibernate-mapping>
Parent p = new Parent();
p.setName("parent");
Child c = (Child) session.load(Child.class, 4l); //原child表中已存在id=4的child
p.getChildren().add(p); // 我但愿用parent端来修改关联,即将id=4的child的外键变为如今这个parent的主键值
session.save(p); //这里保存parent,同时但愿关联也获得修改
可是咱们发现parent确实保存了,而child的外键仍是原值,没有关联到咱们如今的外键
缘由就是咱们将关联的控制方交给了child端,这样一来parent就不可以控制关联了。
Parent p = new Parent();
p.setName("parent");
Child c = (Child) session.load(Child.class, 4l);
c.setParent(p); //这样由child端修改关联就ok了
session.save(p);
Inverse和cascade是Hibernate映射中最难掌握的两个属性。二者都在对象的关联操做中发挥做用。
1.明确inverse和cascade的做用
inverse 决定是否把对对象中集合的改动反映到数据库中,因此inverse只对集合起做用,也就是只对one-to-many或many-to-many有效(因 为只有这两种关联关系包含集合,而one-to-one和many-to-one只含有关系对方的一个引用)。
cascade决定是否把对对象的改动反映到数据库中,因此cascade对全部的关联关系都起做用(由于关联关系就是指对象之间的关联关系)。
2.inverse属性 :inverse所描述的是对象之间关联关系的维护方式。
inverse只存在于集合标记的元素中 。Hibernate提供的集合元素包括<set/> <map/> <list/> <array /> <bag />
Inverse属性的做用是:是否将对集合对象的修改反映到数据库中。
inverse属性的默认值为false,表示对集合对象的修改会被反映到数据库中;inverse=false 的为主动方,由主动方负责维护关联关系。
inverse=”true” 表示对集合对象的修改不会被反映到数据库中。
为了维持两个实体类(表)的关系,而添加的一些属性,该属性可能在两个实体类(表)或者在一个独立的表里面,这个要看这双方直接的对应关系了: 这里的维护指的是当主控放进行增删改查操做时,会同时对关联关系进行对应的更新。
一对多: 该属性在多的一方。应该在一方的设置 inverse=true ,多的一方设置 inverse=false(多的一方也能够不设置inverse属性,由于默认值是false),这说明关联关系由多的一方来维护。若是要一方维护关 系,就会使在插入或是删除"一"方时去update"多"方的每个与这个"一"的对象有关系的对象。而若是让"多"方面维护关系时就不会有update 操做,由于关系就是在多方的对象中的,直指插入或是删除多方对象就好了。显然这样作的话,会减小不少操做,提升了效率。
注:
单向one-to-many关联关系中,不能够设置inverse="true",由于被控方的映射文件中没有主控方的信息。
多对多: 属性在独立表中。inverse属性的默认值为false。在多对多关联关系中,关系的两端 inverse不能都设为false,即默认的状况是不对的,若是都设为false,在作插入操做时会致使在关系表中插入两次关系。也不能都设为 true,若是都设为true,任何操做都不会触发对关系表的操做。所以在任意一方设置inverse=true,另外一方inverse=false。
一对一: 实际上是一对多的一个特例,inverse 的设置也是同样的,主要仍是看关联关系的属性在哪一方,这一方的inverse=false。
多对一: 也就是一对多的反过来,没什么区别。
2.cascade属性
cascade属性的做用是描述关联对象进行操做时的级联特性。所以,只有涉及到关系的元素才有cascade属性。
具 有cascade属性的标记包括<many-to-one /> <one-to-one /> <any /> <set /><bag /> <idbag /> <list /> <array />
注意:<ont-to-many />和 <many-to-many />是用在集合标记内部的,因此是不须要cascade属性的。
级联操做:指当主控方执行某项操做时,是否要对被关联方也执行相同的操做。
3.inverse和cascade的区别
做用的范围不一样:
Inverse是设置在集合元素中的。
Cascade对于全部涉及到关联的元素都有效。
<many-to-one/><ont-to-many/>没有inverse属性,但有cascade属性
执行的策略不一样
Inverse 会首先判断集合的变化状况,而后针对变化执行相应的处理。
Cascade 是直接对集合中每一个元素执行相应的处理
执行的时机不一样
Inverse是在执行SQL语句以前判断是否要执行该SQL语句
Cascade则在主控方发生操做时用来判断是否要进行级联操做
执行的目标不一样
Inverse对于<ont-to-many>和<many-to-many>处理方式不相同。
对于<ont-to-many>,inverse所处理的是对被关联表进行修改操做。
对于<many-to-many>,inverse所处理的则是中间关联表
Cascade不会区分这两种关系的差异,所作的操做都是针对被关联的对象。
总结:
<one-to-many>中,建议inverse=”true”,由“many”方来进行关联关系的维护
<many-to-many>中,只设置其中一方inverse=”false”,或双方都不设置
Cascade,一般状况下都不会使用。特别是删除,必定要慎重。
操做建议 通常对many-to-one和many-to-many不设置级联,这要看业务逻辑的须要;对one-to-one和one-to-many设置级联。 many-to-many关联关系中,一端设置inverse=”false”,另外一端设置为inverse=”true”。在one-to-many关联关系中,设置inverse=”true”,由多端来维护关系表