<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    爪哇一角

    共同探討STRUTS#HIBERNATE#SPRING#EJB等技術(shù)
    posts - 3, comments - 6, trackbacks - 0, articles - 99
      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

    ?????????????????????????????? ?hibernate的inverse和 many-to-many 關(guān)系淺談

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

    這篇文章已經(jīng)詳細分析了inverse設(shè)置不當(dāng)帶來的影響:

    http://www.hibernate.org/155.html

    看了這篇文章,還是很有必要再寫下一些總結(jié)的:

    1)inverse中提及的side其實是指一個類或者表的概念,雙向關(guān)聯(lián)其實是指雙方都可以取得對方的應(yīng)用。

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

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

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

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

    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC
    ?"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
    ?"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
    <hibernate-mapping ?package="org.hibernate.auction">
    ?<class name="TestA" table="TestA"
    ?dynamic-update="true" dynamic-insert="true" >

    ??<id name="id" column="id" type="int" unsaved-value="any" >
    ???<generator class="assigned">
    ???</generator>
    ??</id>

    ??<property name="name" type="java.lang.String"
    ???update="true" insert="true" column="name" />

    ??<set name="testBs" table="TestA_TestB" inverse="false" cascade="all">
    ???<key column="testA"/>
    ???<many-to-many column="testB" class="TestB" />
    ??</set>


    ?</class>
    ?<class name="TestB" table="TestB"
    ?dynamic-update="true" dynamic-insert="true" >

    ??<id name="id" column="id" type="int" unsaved-value="any" >
    ???<generator class="assigned">
    ???</generator>
    ??</id>

    ??<property name="name" type="java.lang.String" update="true"
    ??insert="true" column="name" />

    ??<set name="testAs" table="TestA_TestB" inverse="true" cascade="all">
    ???<key column="testB"/>
    ???<many-to-many column="testA" class="TestA" />
    ??</set>


    ?</class>
    </hibernate-mapping>

    在對多對中,因為一端維護關(guān)系另一端不維護關(guān)系的原因,我們必須注意避免在應(yīng)用中用不維護關(guān)系的類建立關(guān)系,因為這樣建立的關(guān)系是不會在數(shù)據(jù)庫中存儲的?;谏厦娴挠成湮募a給出一個例子:

    package org.hibernate.auction;
    import java.util.*;

    /**
    ?* @author Administrator
    ?*
    ?* To change the template for this generated type comment go to
    ?* Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
    ?*/
    public class TestA {
    ?int id;
    ?String name;
    ?Set testBs=new HashSet();
    ?public TestA(){
    ??
    ?}
    ?public TestA(int id){
    ??setId(id);
    ?}
    ?public int getId(){
    ??return id;
    ?}
    ?public void setId(int id){
    ??this.id=id;
    ?}
    ?public String getName(){
    ??return name;
    ?}
    ?public void setName(String name){
    ??this.name=name;
    ?}
    ?public Set getTestBs(){
    ??return testBs;
    ?}
    ?public void setTestBs(Set s){
    ??testBs=s;
    ?}
    ?public void addTestB(TestB tb){
    ??testBs.add(tb);
    ?}

    ?public static void main(String[] args) {
    ?}
    }

    public class TestB {


    ?int id;
    ?String name;
    ?Set testAs=new HashSet();
    ?public TestB(){
    ??
    ?}
    ?public TestB(int id){
    ??setId(id);
    ?}
    ?public int getId(){
    ??return id;
    ?}
    ?public void setId(int id){
    ??this.id=id;
    ?}
    ?public String getName(){
    ??return name;
    ?}
    ?public void setName(String name){
    ??this.name=name;
    ?}
    ?public Set getTestAs(){
    ??return testAs;
    ?}
    ?public void setTestAs(Set s){
    ??testAs=s;
    ?}
    ?public void addTestA(TestA ta){
    ??testAs.add(ta);
    ?}
    ?public static void main(String[] args) {
    ?}
    }

    測試代碼:

    public void doTest() throws Exception{
    ??TestA a1=new TestA(1);
    ??TestA a2=new TestA(2);
    ??TestA a3=new TestA(3);
    ??TestB b1=new TestB(1);
    ??TestB b2=new TestB(2);
    ??TestB b3=new TestB(3);
    ??a1.addTestB(b1);
    ??a1.addTestB(b2);
    ??a1.addTestB(b3);
    ??b1.addTestA(a1);
    ??b2.addTestA(a2);
    ??
    ??Session s = factory.openSession();
    ??
    ??s = factory.openSession();
    ??
    ??
    ??Session session = factory.openSession();
    ? session.save(a1);
    ? session.flush();
    ? session.close();

    ?}

    測試后連接表的數(shù)據(jù)為:

    testa????????????? testb

    1????????????????? 1

    1????????????????? 2

    1????????????????? 3

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

    /*
    ?* Created on 2004-7-25
    ?*
    ?* To change the template for this generated file go to
    ?* Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
    ?*/
    package org.hibernate.auction;
    import java.util.*;

    /**
    ?* @author Administrator
    ?*
    ?* To change the template for this generated type comment go to
    ?* Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
    ?*/
    public class TestB {


    ?int id;
    ?String name;
    ?Set testAs=new HashSet();
    ?public TestB(){
    ??
    ?}
    ?public TestB(int id){
    ??setId(id);
    ?}
    ?public int getId(){
    ??return id;
    ?}
    ?public void setId(int id){
    ??this.id=id;
    ?}
    ?public String getName(){
    ??return name;
    ?}
    ?public void setName(String name){
    ??this.name=name;
    ?}
    ?public Set getTestAs(){
    ??return testAs;
    ?}
    ?public void setTestAs(Set s){
    ??testAs=s;
    ?}
    ?public void addTestA(TestA ta){
    ??testAs.add(ta);
    ??ta.addTestB(this);
    ?}
    ?public static void main(String[] args) {
    ?}
    }
    那么測試執(zhí)行后連接表的數(shù)據(jù)為:

    testa????????? testb

    1?????????????? 2

    1?????????????? 3

    1??????????????? 1

    2???????????????? 2

    測試通過。

    主站蜘蛛池模板: 亚洲视频在线免费播放| 日本一区午夜艳熟免费| 美女视频黄a视频全免费| 亚洲精品高清久久| 久久免费美女视频| 亚洲性天天干天天摸| 美女内射无套日韩免费播放| 亚洲avav天堂av在线不卡| 三年片在线观看免费| 亚洲人成电影在线天堂| 国产2021精品视频免费播放| 亚洲国产高清在线精品一区| 在线天堂免费观看.WWW| 亚洲色一区二区三区四区| 日韩视频在线免费观看| 黄色一级免费网站| 亚洲综合无码AV一区二区| 久久精品免费电影| 亚洲jizzjizz在线播放久| 永久免费av无码网站大全| 无码精品人妻一区二区三区免费| 国产成人高清亚洲| 免费无码成人AV在线播放不卡| 亚洲高清美女一区二区三区| 国产免费观看a大片的网站| 亚洲A∨精品一区二区三区下载| 伊在人亚洲香蕉精品区麻豆| 最新久久免费视频| 亚洲国产精品张柏芝在线观看| 成在人线AV无码免费| 欧洲美女大片免费播放器视频| 亚洲产国偷V产偷V自拍色戒| 国产AV无码专区亚洲AV蜜芽 | 国产精品99精品久久免费| 亚洲精品在线免费看| 日韩中文无码有码免费视频 | 国产乱子伦片免费观看中字| 你是我的城池营垒免费看| 2020年亚洲天天爽天天噜| 亚洲不卡AV影片在线播放| 欧洲精品99毛片免费高清观看|