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」,由多端來維護關係表