hibernate cascade,inverse和lazy的用法

設置 inverse=”false” cascade=”save-update” ,刪除父表記錄時,子表對應外鍵置空。

設置 inverse=”false” cascade=”all”,刪除父表記錄時,子表級聯刪除。

1. hibernate 級聯關係說明 - 關於cascade和inverse的用法 http://www.diybl.com/course/3_program/java/javashl/2008326/107345.html

在hibernate中一對多關聯時會經常用到inverse和cascade屬性 ,

inverse 有兩個值 true ,false  ;如果設置爲true 則表示當前對象不負責講級聯對象的狀態變化同步到數據庫 ;設置false則相反,其默認值爲false;

cascade 有五個選項 分別是: all ,delete ,none,save-update,delete-orphan ;
all : 所有情況下均進行關聯操作。
none:所有情況下均不進行關聯操作。這是默認值。
save-update:在執行save/update/saveOrUpdate時進行關聯操作。
delete:在執行delete時進行關聯操作。
delete-orphan: 當save/update/saveOrUpdate時,相當於save-update ;當刪除操作時,相當於delete ;

all的意思是save-update + delete
all-delete-orphan 的意思是當對象圖中產生孤兒節點時,在數據庫中刪除該節點
all比較好理解,舉個例子說一下all-delete-orphan:
Category與Item是一對多的關係,也就是說Category類中有個Set類型的變量items.
舉個例子,現items中存兩個Item, item1,item2,如果定義關係爲all-delete-orphan
當items中刪除掉一個item(比如用remove()方法刪除item1),那麼被刪除的Item類實例
將變成孤兒節點,當執行category.update(),或session.flush()時
hibernate同步緩存和數據庫,會把數據庫中item1對應的記錄刪掉

測試Hibernate中的三個屬性:lazy,inverse,cascade

【測試環境】
一對多關係的兩張表:boy、girl(一個男孩可以多個女朋友)

boy表結構
Field   Type
——  ———–
name    varchar(50)  pk
age     varchar(50)

girl表結構
Field   Type
——  ———–
name    varchar(50)  pk
bf      varchar(50)  fk 

【保存時:Inverse與cascade】

創建三個girl對象和一個boy對象,讓這是三個girl都是boy的女朋友

———創建對象的代碼片段———–
Boy boy = new Boy(“tom”,”23″, null);

Set girls = new HashSet();

Girl g[] = new Girl[]{
new Girl(“Alice1″, boy),
new Girl(“Alice2″, boy),
new Girl(“Alice3″, boy)};
girls.add(g[0]);
girls.add(g[1]);
girls.add(g[2]);

boy.setGirls(girls);

在Boy.hbm.xml中設置,然後對boy對象進行保存。

1.Inverse = true,不指定cascade
cascade的默認值爲none, 當對boy進行保存操作時,girl什麼都不做. 所以只保存了boy對象, 沒有保存girl對象

2.Inverse = true,cascade=all
boy與girl對象,包擴外鍵都成功保存。
(生成3條SELECT語句和4條INSERT語句,一下簡稱SELECT 3, INSERT 4)

3.Inverse = false,不指定cascade
報錯。因爲boy爲主控方,負責維護關係,所以在插入boy對象後,會嘗試修改並不存在的girl對象。

4.Inverse = false,cascade=all
boy與girl對象,包擴外鍵都成功保存。
(SELECT 4, INSERT 4, UPDATE 3)

分析:除了4條INSERT語句之外,其他的6條語句是我們爲了圖方便付出的代價:3條SELECT語句用來判斷girl對象是否在數據表中已經存在,3條UPDATE語句是爲了維護外鍵關係

高效率的做法:在Boy.hbm.xml中設置Inverse=true,在Girl.hbm.xml中設置Inverse=false, cascade=all,然後保存三個girl對象
(SELECT 1, INSERT 4)

高效率的代價就是保存的時候比較麻煩

【刪除時:Inverse與cascade】

希望通過刪除boy,也將3個girl對象刪除。程序中先查出boy對象,然後進行刪除
—————————————–
Boy boy = (Boy) s.get(Boy.class, “tom”);
s.delete(boy);
—————————————–
同樣在Boy.hbm.xml中進行設置

1.Inverse = true
可以猜到結果是出錯。原因:外鍵約束錯誤

2.Inverse = false
boy刪除,girl表中外鍵變爲null,沒有刪除記錄 ;
(UPDATE 1, DELETE 1)

3.Inverse = false, cascade = all
全部刪除  ;在刪除有外鍵的從表時,先把從表外鍵置爲null,然後刪除主表記錄,最後根據從表主鍵刪除所有相關從表記錄

(UPDATE 1, DELETE 4)

4.Inverse = true, cascade = all
全部刪除
(DELETE 4)

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

這篇文章已經詳細分析了inverse設置不當帶來的影響:

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

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

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

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

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

4)我們說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/>。

<?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>
</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” />
</set>
</class>
<class name=”TestB” table=”TestB”
dynamic-update=”true” dynamic-insert=”true” >

<id name=”id” column=”id” type=”int” unsaved-value=”any” >
<generator>
</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” />
</set>
</class>
</hibernate-mapping>

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

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);
b2.addTestA(a1);
b2.addTestA(a2);

Session s = factory.openSession();

s = factory.openSession();

Session session = factory.openSession();
session.save(a1);
session.flush();
session.close();

}

測試後連接表的數據爲:

testa              testb

1                  1

1                  2

1                  3

根據inverse規則,對這些代碼:b2.addTestA(a1);  b2.addTestA(a2); 建立的關係,數據庫並沒有存儲下來,因爲TestB沒有責任維護這些關係,所以產生的sql語句自然不會有針對Testa_testB表的操作了。假設應 用中真的需要這些方法,那麼我們可以修改TestB的方法,讓他們注意在維護端類中執行相應的操作以使得關係能夠在數據庫中保存下來,更改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) {
}
}
那麼測試執行後連接表的數據爲:

testa          testb

1               2

1               3

1                1

2                 2

測試通過。

附 hibernate cascade備忘 :
當關聯雙方存在父子關係,就可以在 set 處設定 cascade 爲 all-delete-orphan

所謂父子關係,即指由父方控制子方的持久化聖明週期,子方對象必須和一個父方對象關聯。如果刪除父方對象,應該級聯刪除所有關聯的子方對象;如果一個子方對象不再和一個父方對象關聯,應該把這個子方對象刪除。

all-deleteorphan 的能力:

1. 當保存或更新父方對象時,級聯保存或更新所有關聯的子方對象,相當於 cascade 爲 save-update

2. 當刪除父方對象時,級聯刪除所有關聯的子方對象,相當於 cascade 爲 delete

3. 刪除不再和父方對象關聯的所有子方對象

解除父子關係的 java 語句例如:

customer.getOrders().remove(order);
order.setCustomer(null);

tx.commit();

如果 cascade 屬性取默認值 null,當解除父子關係時,會執行如下 sql:

update ORDER set CUSTOMER_ID=null where ID=2

inverse 設定的原則:

1. 在映射一對多雙向關聯關係時,應該設定 many 方的 inverse 爲 true,以提高性能

2. 在建立兩個對象的雙向關聯時,應同時修改關聯兩端的對象的相應屬性:

1)customer.getOrders().add(order);
2)order.setCustomer(customer);

如果不執行 1)而僅執行 2),由於 set 元素的 inverse 爲 true,因此 hibernate 不會按照 CUSTOMER 對象的狀態變化來同步數據庫。

inverse 解決性能問題的例子:

1. 建立 Order 到 Customer 的多對一關聯關係

order.setCustomer(customer);

相應執行的 SQL 爲:

update ORDERS set ORDER_NUMBER=”Jack_Order001”, CUSTOMER_ID=2 where ID=2;

2. 建立 Customer 到 Order 的一對多關係

customer ORDERS set CUSTOMER_ID=2 where ID=2;

相應 SQL 爲:

update ORDERS set CUSTOMER_ID=2 where ID=2;

顯然 1 和 2 的 SQL 功能重複了,反覆執行這樣的 SQL 語句會引起性能下降,因此:

inverse 設定爲 true 時,聲明 Customer 端的關聯只是 Order 端關聯的鏡像。當兩者狀態發生變化時,Hibernate 僅按照 Order 對象狀態變化來同步數據庫。即僅會執行以下 SQL:

update ORDERS set ORDER_NUMBER=”Jack_Order001”, CUSTOME_ID=2 where ID=2;

Customer.hbm.xml 片段如下:

<set
name=”orders”
cascade=”all-delete-orphan”
inverse=”true”
>
<key column=”CUSTOMER_ID” />
<one-to-many />
</set>

引用:http://huhu0817.javaeye.com/blog/97831

2. (Hibernate)cascade http://blog.csdn.net/daniel_tu/article/details/3932078

利用關聯關係操作對象:
數據對象之間的關聯關係有一對一,一對多及多對多三種。在數據庫操作中,數據對象之間的關聯關係使用JDBC處理很困難。例如,當刪除一個班級的信息時,還要刪除該班級的所有學生的基本信息。如果直接使用JDBC執行這種級聯操作,會非常繁鎖。Hibernate通過把實體對象之間的關聯關係及級聯關係在映射文件中聲明,比較簡單地解決了這類級聯操作問題。
一對一關聯關係的使用:
一對一關聯關係在實際生活中是比較覺的,例如學生與學生證的關係,通過學生證可以找到學生。一對一關聯關係在Hibernate中的實現有兩種方式,分別是主鍵關聯和外鍵關聯。
主鍵關聯:
主鍵關聯的重點是,關聯兩個實體共享一個主鍵值。例如student與card是一對一關係,它們在數據庫中對應的表分別是t_student和 t_card。它們共用一個主鍵值ID,這個主鍵可由t_student或t_card表生成。問題是如何讓另一張表引用已經生成的主鍵值呢?例如,t_student表未老先衰了ID的值,t_card表如何引用它?這需要在Hibernate的映射文件中使用主鍵的foreign生成機制!

爲了表示Student與Card之間的一對一的關聯關係,我們需要在它們各自的映射文件 中都要使用<one-to-one>標記!
一對一關係我在前面已經寫過例子程序了,在這裏僅給出兩個映射文件。如下:
學生PO映射信息:

<?xml version=”1.0″ encoding=”GBK”?>
<!DOCTYPE hibernate-mapping PUBLIC ”-//Hibernate/Hibernate Mapping DTD 3.0//EN”
“http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd”>

<hibernate-mapping>
    <class name=”hibernate.PO.TStudent” table=”t_student” lazy=”true”><!–把類與表關聯起來 –>
        <id name=”id” type=”java.lang.Integer”>
            <column name=”id”/>
            <generator class=”increment” />
        </id>
        <property name=”userName” type=”java.lang.String”>
            <column name=”userName” length=”20″ />
        </property>
        <property name=”cardId” type=”java.lang.String”>
            <column name=”card_id” length=”20″ />
        </property>
        <property name=”sex” type=”java.lang.String”>
            <column name=”sex” length=”2″ />
        </property>
        <property name=”age” type=”java.lang.Integer”>
            <column name=”age” />
        </property>
        <one-to-one name=”card” class=”hibernate.PO.TCard” fetch=”join” cascade=”all” />
    </class>
</hibernate-mapping>
<!–
class元素的lazy屬性設定爲true,表示延遲加載,如果lazy設爲false,則
表示立即加載。以下對這二點進行說明。
    立即加載:表示Hibernate在從數據庫中取得數據組裝好一個對象(如學生1)後,
            會立即再從數據庫取得數據組裝此對象所關聯的對象(如學生證1)。
    延遲加載:表示Hibernate在從數據庫中取得數據組裝好一個對象(如學生1)後,
            不會立即再從數據庫中取得數據組裝此對象所關聯的對象(如學生1),
            而是等到需要時,纔會從數據庫取得數據組裝此關聯對象。
<one-to-one>元素的cascade屬性表明操作是否從父對象級聯到被關聯的對象,    它
的取得可以是以下幾種:
    none:在保存,刪除或修改當前對象時,不對其附屬對象(關聯對象)進行級聯
          操作。它是默認值。
    save-update:在保存,更新當前對象時,級聯保存,更新附屬對象(臨時對象,
          遊離對象)。
    delete:在刪除當前對象時,級聯刪除附屬對象。
    all:所有情況下均進行級聯操作,即包含save-update和delete操作。
    delete-orphan:刪除和當前對象解除關係的附屬對象。
<one-to-one>元素的fetch屬性的可選值是join和select,默認是select。
當fetch屬性設定爲join時,表示連接抓取(Join fetching):Hibernate通過
在Select語句中使用outer join(外連接)來獲得對象的關聯實例或者關聯集合。
當fetch屬性設定爲select時,表示查詢抓取(Select fetching):需要另外發
送一條Select語句抓取當前對象的關聯實體或集合。–>

學生證PO映射信息:

<?xml version=”1.0″ encoding=”GBK”?>
<!DOCTYPE hibernate-mapping PUBLIC ”-//Hibernate/Hibernate Mapping DTD 3.0//EN”
“http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd”>

<hibernate-mapping>
    <class name=”hibernate.PO.TCard” table=”t_card” lazy=”true”>
        <id name=”id” type=”java.lang.Integer”>
            <column name=”id”/>
            <generator class=”foreign”>
                <param name=”property”>student</param>
            </generator>
        </id>
        <!– id使用外鍵(foreign)生成機制,引用代號爲student的對象
             的主鍵作爲T_card表的主鍵和外鍵。同時student在下面的
             <one-to-one>中進行了定義 –>
        <property name=”name” type=”java.lang.String”>
            <column name=”name” length=”20″ />
        </property>


          <one-to-one name=”student” class=”hibernate.PO.TStudent” constrained=”true” />
          <!– constrained=”true”表示Card引用了student的主鍵作爲外鍵。 –>
    </class>
</hibernate-mapping>

外鍵關聯:
外鍵關聯的要點是:兩個實體各自有不同的主鍵,但其中一個實體有一個外鍵引用另一個實體的主鍵。例如,假設,Student和Card是外鍵關聯的一對一關係們在數據庫中相應的表分別如下:t_student表有一個主鍵ID,t_card表有一個主鍵ID和一個外鍵student_id,此外鍵對應 t_student表的主鍵ID,那麼student的映射信息如上面一樣不做改動,而Card的映射文件要做相應的改動。如下:

<hibernate-mapping>
    <class name=”hibernate.PO.TCard” table=”t_card” lazy=”true”>
        <id name=”id” type=”java.lang.Integer”>
            <column name=”id”/>
            <generator class=”increment”/><!– 不再是foreign了 –>
        </id>

        <property name=”name” type=”java.lang.String”>
            <column name=”name” length=”20″ />
        </property>

       <many-to-one name=”student” column=”student_id” class=”hibernate.PO.TStudent” unique=”true”/>
       <!– 惟一的多對一,實際上變成一對一關係了 –>
         <!– unique設爲true表示使用DDL爲外鍵字段生成一個惟一約束。
                 以外鍵關聯對象的一對一關係,其本質上已經變成了一對多的雙向關聯,
                 應直接按照一對多和多對一的要求編寫它們的映射文件。當unique爲
                 true時實際上變成了一對一的關係。 –>

    </class>
</hibernate-mapping>

一對多關聯關係的使用
一對多關係很覺,例如班級與學生的關係就是典型的一對多的關係。在實際編寫程序時,一對多關係有兩種實現方式:單向關聯和雙向關聯。單向的一對多關係只需要在一方進行映射配置,而雙向的一對多需要在關聯的雙方進行映射配置。下面以Group(班級)和Student(學生)爲例講解如何配置一對多的關係。
單向關聯:
單向的一對多關係只需要在一方進行映射配置,所以我們只配置Group的映射文件:

<hibernate-mapping>
    <class name=”hibernate.PO.Group” table=”t_group” lazy=”true”>
        <id name=”id” type=”java.lang.Integer”>
            <column name=”id”/>
            <generator class=”increment”/>
        </id>
        <!– insert屬性表示被映射的字段是否出現在SQL的INSERT語句中 –>
        <property name=”name” type=”java.lang.String” update=”true” insert=”true”>
            <column name=”name” length=”20″ />
        </property>

        <!– set元素描述的字段對應的類型爲java.util.Set類型。
            inverse用於表示雙向關聯中的被動一端。inverse的值
            爲false的一方負責維護關聯關係。
            sort排序關係,其可選值爲:unsorted(不排序)。
                                  natural(自然排序)。
                                  comparatorClass(由某個實現了java.util.comparator接口的類型指定排序算法。)
            <key>子元素的column屬性指定關聯表(t_student表)的外鍵。
       –>
        <set name=”students”
             table=”t_student”
             lazy=”true”
             inverse=”false”
             cascade=”all”
             sort=”unsorted”>
        <key column=”ID”/>
        <one-to-many class=”hibernate.PO.TStudent”/>
        </set>
    </class>
</hibernate-mapping>

雙向關聯:
如果要設置一對多雙向關聯關係,那麼還需要在“多”方的映射文件中使用<many-to-one>標記。例如,在Group與Student一對多的雙向關聯中,除了Group的映射文件外還需要在Student的映射文件中加入如下代碼:

 <many-to-one name=”group”
                     class=”Group”
                     cascade=”none”
                     outer-join=”auto”
                     update=”true”
                     insert=”true”
                     column=”ID” />

inert和update設定是否對column屬性指定的關聯字段進行insert和update操作。
此外將Group.hbm.xml中<set>元素的inverse設置爲true.多對多關聯關係的使用
Student(學生)和Course(課程)的關係就是多對多關係。在映射多對多關係時需要另外使用一個連接表(如Student_Course)。 Student_Course表包含二個字段:courseID和studentID。此處它們的映射文件中使用<many-to- many>標記,在Student的映射文件中加入以下描述信息:

  <set name=”courses”
               table=”student_course”
               lazy=”false”
               inverse=”false”
               cascade=”save-update”>
               <key column=”studentID” />
           <many-to-many class=”Course” column=”CourseID”/>
           </set>

相應的Course的映射文件中加入以下:

 <set name=”students”
               table=”student_course”
               lazy=”false”
               inverse=”true”
               cascade=”save-update”>
               <key column=”CourseID” />
           <many-to-many class=”Student” column=”StudentID”/>
           </set>

添加關聯關係:
首先編寫一個程序來看看一個名爲Bill的學生選擇了什麼課程:

//獲取代表Bill的Student對象
        Student stu = (Student)session.createQuery(“from Student s where s.name=’Bill’”).uniqueResult();
        List list = new ArrayList(stu.getCourses());
        for(int i = 0 ; i < list.size(); i++)
        {
            Course course = (Course)list.get(i);//取得Course對象
            System.out.println(course.getName());//打印出Bill所選課程的清單
        }

現在Bill還想chemistry課程,這對於程序員來說只是爲Bill添加一個到chemistry的關聯,也就是說在student_course表中新增加一條記錄,而T_student和T_Course表都不用變更。

//獲取代表Bill的Student對象
        Student stu = (Student)session.createQuery(“from Student s where s.name=’Bill’”).uniqueResult();
        Course course = (Course)session.createQuery(“from Course c where c.name=’chemistry’”).uniqueResult();
        //設置stu與course的關聯關係
        stu.getCourses().add(course);
        course.getStudents().add(stu);

刪除關聯關係:
刪除關聯關係比較簡單,直接調用對象集合的remove()方法刪除不要的對象就可。例如:要從學生Bill的選課清單中刪除politics和chemistry兩門課,程序代碼如下:

        //獲取代表Bill的Student對象
        Student stu = (Student)session.createQuery(“from Student s where s.name=’Bill’”).uniqueResult();
        Course course1 = (Course)session.createQuery(“from Course c where c.name=’politics’”).uniqueResult();
        Course course2 = (Course)session.createQuery(“from Course c where c.name=’chemistry’”).uniqueResult();
        stu.getCourse().remove(course1);//刪除politics課程
        stu.getCourse().remove(course2);//刪除chemistry課程

運行以上程序將從student_course表中刪除這兩條記錄,但T_student和T_course表沒有任何變化

發佈了9 篇原創文章 · 獲贊 153 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章