天天看點

Hibernate inverse 字段

控制翻轉,一般用在多對一,一對多關系中,      
相當于多個人記同一個人的名字很好記,一個人記多個人的名字就麻煩了       
我們一般建議在一對多雙向關聯關系中,      
将一(即少的一方)方的inverse屬性設定為true,即将主外鍵的關系交由多(即多的一方)方來維護。      
打個比方:在一個公司中,是老闆認識所有的員工容易,還是所有員工認識老闆容易?
      
inverse常用于一對多雙向關聯關系中。
以Student(學生)和Class(班級)為例,它們之間的關系為一對多的關系,即一個學生隻能屬于一個班級,一個班級可以包含多個學

生。
學生類定義代碼:
Class Student{
  private int id;
  private String name;
  private Class class;
  //省略getter()和setter()方法
}
班級類定義代碼:
Class Class{
  private int id;
  private String name;
  private Set students = new HashSet();
  //省略getter()和setter()方法
}
Student類的映射檔案:
<class name="Student" table="STUDENT">
   <id name="id" type="int" column="ID">
      <generator class="native" />  
   </id>
   <property name="name" type="string" column="NAME" />
   <many-to-one name="class" column="CLASS_ID" class="Class" cascade="save-update" /> 
</class>
Class類的映射檔案:
<class name="Class" table="CLASS">
   <id name="id" type="int" column="ID">
     <generator class="native" />  
   </id>
   <property name="name" type="string" column="NAME" />
   <set name="students" table="STUDENT" cascade="save-update" inverse="false">
     <key column="CLASS_ID" />
     <one-to-many class="Student" />
   </set>
</class>
希望你能對這兩個映射檔案所表達的資料庫模式有正确的認識。即STUDENT表中存在一個名為CLASS_ID的字段,它和CLASS表中的ID字段是主外鍵關系。那個inverse屬性就是用來規定是由誰(Student或Class)來維護這個主外鍵關系的。
inverse的預設值為false。
在處理邏輯代碼中,如下:
Class c1 = new Class();
c1.setName("一班");
Student s1 = new Student();
Student s2 = new Student();
s1.setName("Jason");
s2.setName("Tom");
c1.getStudents().add(s1);
c2.getStudents().add(s2);
s1.setClass(c1);
s2.setClass(c1);   //注釋1
session.save(c1);
上面的代碼會使Hibernate執行五條SQL語句,其中前三條是insert插入語句,後兩條是update更新語句。插入就不用說了,那麼為什麼還要有更新語句呢?這是因為Class類映射檔案的<set>元素中指定了inverse="false",這就告之Hibernate:STUDENT表與CLASS表的主外鍵關系是由Class類來維護的。當執行save後,執行了三條insert語句,這三條語句中的後兩條是插入到STUDENT表的,它們的CLASS_ID字段是通過s1.getClass().getID()取出的,假如我将上面“注釋1”處修改為s2.setClass(c2);(c2是另一個Class對象,可能是持久化對象),這樣,主外鍵關系不就亂了嗎。為了保證主外鍵關系,Hibernate在這種情況下會再執行兩條update語句來更改STUDENT表中兩個新插入記錄的CLASS_ID字段,當然,這時CLASS_ID字段的取值是從c1對象中直接取得,而不再是s1.getClass().getID()方式了。
如果我們将Class類映射檔案的<set>元素中的inverse屬性修改為true,這就是告訴Hibernate:Class類不維護主外鍵關系了,這個任務就交給了Student類。于是,我們再執行上面的代碼,Hibernate就會隻執行三條insert語句,而不會執行任何update語句。因為Hibernate會通過Student類的s1.getClass().getID()和s2.getClass().getID()來确定CLASS_ID字段的值。
故,為了節省資料庫資源,省卻不必要的update語句,我們一般建議在一對多雙向關聯關系中,将一方的inverse屬性設定為true,即将主外鍵的關系交由多方來維護。
打個比方:在一個公司中,是老闆認識所有的員工容易,還是所有員工認識老闆容易?