posts - 64,  comments - 9,  trackbacks - 0

          通過Hibernate Inverse的設置來決定是由誰來維護表和表之間的關系。最近有朋友問我Hibernate關于多對多關于刪除中間表數據的問題,關鍵是Inverse的設置,下面引用網友的一篇文章。

          Inverse是Hibernate雙向關系中的基本概念,當然對于多數實體,我們并不需要雙向關聯,更多的可能會選擇單向關聯,況且我們大多數人 一般采用一對多關系,而一對多雙向關聯的另一端:多對一的Inverse屬性是不存在,其實它默認就是Inverse=false.從而防止了在一對多端 胡亂設置Inverse也不至于出錯。但是Inverse設置不當確實會帶來很大的性能影響,這點是我們必須關注的。

          這篇文章已經詳細分析了Hibernate Inverse設置不當帶來的影響:http://www.Hibernate.org/155.html,看了這篇文章,還是很有必要再寫下一些總結的:

          1)Hibernate Inverse中提及的side其實是指一個類或者表的概念,雙向關聯其實是指雙方都可以取得對方的應用。

          2)維護關系這個名詞還是稍顯模糊或者晦澀。我們一般說A類或者A表(這里的表的是指多對多的連接表)有責任維護關系,其實這里的意思是說,我在應 用在更新,創建,刪除(讀就不用說了,雙向引用正是為了方便讀而出現)A類或者A表時,此時創建的SQL語句必須有責任保證關系的正確修改。

          3)Inverse=false的side(side其實是指Inverse=false所位于的class元素)端有責任維護關系,而Inverse=true端無須維護這些關系。

          4)我們說Hibernate Inverse設立不當會導致性能低下,其實是說Inverse設立不當,會產生多余重復的SQL語句甚至致使JDBC exception的throw。這是我們在建立實體類關系時必須需要關注的地方。一般來說,Inverse=true是推薦使用,雙向關聯中雙方都設置 Inverse=false的話,必會導致雙方都重復更新同一個關系。但是如果雙方都設立Inverse=true的話,雙方都不維護關系的更新,這也是 不行的,好在一對多中的一端:many-to-one默認是Inverse=false,避免了這種錯誤的產生。但是多對多就沒有這個默認設置了,所以很 多人經常在多對多的兩端都使用Inverse=true,結果導致連接表的數據根本沒有記錄,就是因為他們雙分都沒有責任維護關系。所以說,雙向關聯中最 好的設置是一端為Inverse=true,一端為Inverse=false。一般Inverse=false會放在多的一端,那么有人提問了, many-to-many兩邊都是多的,Inverse到底放在哪兒?其實Hibernate建立多對多關系也是將他們分離成兩個一對多關系,中間連接一 個連接表。所以通用存在一對多的關系,也可以這樣說:一對多是多對多的基本組成部分。

          看下面的多對多的定義大家更會清楚”多對多“與“一對多”的關系:其中我們注意<many-to-many />標簽的特點就知道,它是定義了一個多對多關系,而不是<one-to-many/>。

          1. <?xml version="1.0"?>   
          2. <!DOCTYPE Hibernate-mapping PUBLIC   
          3. "-//Hibernate/Hibernate Mapping DTD 2.0//EN"   
          4. "http://Hibernate.sourceforge.net/Hibernate-mapping-2.0.dtd">   
          5. <Hibernate-mapping package="org.Hibernate.auction">   
          6. <class name="TestA" table="TestA"   
          7. dynamic-update="true" dynamic-insert="true" >  
          8.    <id name="id" column="id" type="int" unsaved-value="any" >   
          9.     <generator class="assigned">   
          10.     </generator>   
          11.    </id>  
          12.    <property name="name" type="java.lang.String"   
          13.     update="true" insert="true" column="name" />  
          14.    <set name="testBs" table="TestA_TestB" Inverse="false" cascade="all">   
          15.     <key column="testA"/>   
          16.     <many-to-many column="testB" class="TestB" />   
          17.    </set>  
          18. </class>   
          19. <class name="TestB" table="TestB"   
          20. dynamic-update="true" dynamic-insert="true" >  
          21.    <id name="id" column="id" type="int" unsaved-value="any" >   
          22.     <generator class="assigned">   
          23.     </generator>   
          24.    </id>  
          25.  
          26.    <property name="name" type="java.lang.String" update="true"   
          27.    insert="true" column="name" />  
          28.  
          29.    <set name="testAs" table="TestA_TestB" Inverse="true" cascade="all">   
          30.     <key column="testB"/>   
          31.     <many-to-many column="testA" class="TestA" />   
          32.    </set>  
          33. </class>   
          34. </Hibernate-mapping> 

          在對多對中,因為一端維護關系另一端不維護關系的原因,我們必須注意避免在應用中用不維護關系的類建立關系,因為這樣建立的關系是不會在數據庫中存儲的。基于上面的映射文件代碼給出一個例子:

          1. package org.Hibernate.auction;   
          2. import java.util.*;  
          3. /**   
          4. * @author Administrator   
          5.  
          6. * To change the template for this generated type comment go to   
          7. * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments   
          8. */   
          9. public class TestA {   
          10. int id;   
          11. String name;   
          12. Set testBs=new HashSet();   
          13. public TestA(){   
          14. }   
          15. public TestA(int id){   
          16.    setId(id);   
          17. }   
          18. public int getId(){   
          19.    return id;   
          20. }   
          21. public void setId(int id){   
          22.    this.id=id;   
          23. }   
          24. public String getName(){   
          25.    return name;   
          26. }   
          27. public void setName(String name){   
          28.    this.name=name;   
          29. }   
          30. public Set getTestBs(){   
          31.    return testBs;   
          32. }   
          33. public void setTestBs(Set s){   
          34.    testBs=s;   
          35. }   
          36. public void addTestB(TestB tb){   
          37.    testBs.add(tb);   
          38. }public static void main(String[] args) {   
          39. }   
          40. }  
          41. public class TestB {  
          42. int id;   
          43. String name;   
          44. Set testAs=new HashSet();   
          45. public TestB(){   
          46. }   
          47. public TestB(int id){   
          48.    setId(id);   
          49. }   
          50. public int getId(){   
          51.    return id;   
          52. }   
          53. public void setId(int id){   
          54.    this.id=id;   
          55. }   
          56. public String getName(){   
          57.    return name;   
          58. }   
          59. public void setName(String name){   
          60.    this.name=name;   
          61. }   
          62. public Set getTestAs(){   
          63.    return testAs;   
          64. }   
          65. public void setTestAs(Set s){   
          66.    testAs=s;   
          67. }   
          68. public void addTestA(TestA ta){   
          69.    testAs.add(ta);   
          70. }   
          71. public static void main(String[] args) {   
          72. }   

          測試代碼:

          1. public void doTest() throws Exception{   
          2.    TestA a1=new TestA(1);   
          3.    TestA a2=new TestA(2);   
          4.    TestA a3=new TestA(3);   
          5.    TestB b1=new TestB(1);   
          6.    TestB b2=new TestB(2);   
          7.    TestB b3=new TestB(3);   
          8.    a1.addTestB(b1);   
          9.    a1.addTestB(b2);   
          10.    a1.addTestB(b3);   
          11.    b2.addTestA(a1);   
          12.    b2.addTestA(a2);   
          13.    Session s = factory.openSession();   
          14.    s = factory.openSession();   
          15.    Session session = factory.openSession();   
          16. session.save(a1);   
          17. session.flush();   
          18. session.close();  

          測試后連接表的數據為:

          testa              testb

          1                  1

          1                  2

          1                  3

          根據Inverse規則,對這些代碼:b2.addTestA(a1);   b2.addTestA(a2); 建立的關系,數據庫并沒有存儲下來,因為TestB沒有責任維護這些關系,所以產生的sql語句自然不會有針對Testa_testB表的操作了。假設應 用中真的需要這些方法,那么我們可以修改TestB的方法,讓他們注意在維護端類中執行相應的操作以使得關系能夠在數據庫中保存下來,更改TestB如 下:

          1. /*   
          2. * Created on 2004-7-25   
          3.  
          4. * To change the template for this generated file go to   
          5. * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments   
          6. */   
          7. package org.Hibernate.auction;   
          8. import java.util.*;  
          9. /**   
          10. * @author Administrator   
          11.  
          12. * To change the template for this generated type comment go to   
          13. * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments   
          14. */   
          15. public class TestB {  
          16. int id;   
          17. String name;   
          18. Set testAs=new HashSet();   
          19. public TestB(){   
          20. }   
          21. public TestB(int id){   
          22.    setId(id);   
          23. }   
          24. public int getId(){   
          25.    return id;   
          26. }   
          27. public void setId(int id){   
          28.    this.id=id;   
          29. }   
          30. public String getName(){   
          31.    return name;   
          32. }   
          33. public void setName(String name){   
          34.    this.name=name;   
          35. }   
          36. public Set getTestAs(){   
          37.    return testAs;   
          38. }   
          39. public void setTestAs(Set s){   
          40.    testAs=s;   
          41. }   
          42. public void addTestA(TestA ta){   
          43.    testAs.add(ta);   
          44.    ta.addTestB(this);   
          45. }   
          46. public static void main(String[] args) {   
          47. }   
          48. }  

          那么測試執行后連接表的數據為:

          testa          testb

          1               2

          1               3

          1               1

          2               2

          測試通過。

          posted on 2009-07-30 12:04 super_nini 閱讀(1462) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          <2009年7月>
          2829301234
          567891011
          12131415161718
          19202122232425
          2627282930311
          2345678

          常用鏈接

          留言簿

          隨筆檔案

          文章檔案

          相冊

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 宽甸| 靖边县| 焉耆| 成都市| 商洛市| 衡南县| 乌什县| 得荣县| 突泉县| 海门市| 东乡县| 庆城县| 喀喇沁旗| 镇赉县| 南岸区| 石棉县| 龙陵县| 武定县| 灌阳县| 宁乡县| 滁州市| 新巴尔虎左旗| 师宗县| 昆明市| 文登市| 永年县| 澄江县| 峡江县| 常山县| 平昌县| 商都县| 遵义县| 宁波市| 达孜县| 石景山区| 永寿县| 牡丹江市| 民县| 利津县| 洞口县| 澄迈县|