在 Hibernate 中inverse的屬性


hibernate配置文件中有這么一個屬性inverse,它是用來指定關聯的控制方的。
inverse屬性默認是false,若為false,則關聯由自己控制,若為true,則關聯
由對方控制。
見例子:

一個Parent有多個Child,一個Child只能有一個Parent。

package com.xian;

public class Child {
 private Long id;
 private String name;
 private Parent parent;

 public Long getId() {
  return id;
 }

 public void setId(Long id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public Parent getParent() {
  return parent;
 }

 public void setParent(Parent parent) {
  this.parent = parent;
 }

}


<?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”,由多端來維護關系表


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM