Hibernate 菜鳥(niǎo)教程 5 雙向多對(duì)一

主要講解inverse和cascade的用法

cascade定義的是關(guān)系兩端對(duì)象到對(duì)象的級(jí)聯(lián)關(guān)系凳忙;
而inverse定義的是關(guān)系和對(duì)象的級(jí)聯(lián)關(guān)系(管理外鍵的值)饥努。

inverse

屬性默認(rèn)是false的,就是說(shuō)關(guān)系的兩端都來(lái)維護(hù)關(guān)系颜屠。
在雙向多對(duì)一里面配置到一方的集合屬性上面,inverse=true,表示關(guān)系的維護(hù)(外鍵的值)由對(duì)方(多方)來(lái)管理

cascade

all : 所有情況下均進(jìn)行關(guān)聯(lián)操作蚊荣。
none:所有情況下均不進(jìn)行關(guān)聯(lián)操作。這是默認(rèn)值莫杈。
save-update:在執(zhí)行save/update/saveOrUpdate時(shí)進(jìn)行關(guān)聯(lián)操作互例。
delete:在執(zhí)行delete時(shí)進(jìn)行關(guān)聯(lián)操作。
delete-orphan:刪除解除關(guān)系的orphan兒子

映射文件Dept.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.jege.hibernate.two.way.onetomany">
    <class name="Dept" table="t_dept">
        <id name="id">
            <generator class="native" />
        </id>
        <property name="name" />
        <set name="users" inverse="true">
            <key column="dept_id" />
            <one-to-many class="User" />
        </set>
    </class>
</hibernate-mapping>

測(cè)試類(lèi)TwoCrudTest.java

package com.jege.hibernate.two.way.onetomany;

import java.util.Set;

import org.hibernate.Query;
import org.hibernate.Session;
import org.junit.Before;
import org.junit.Test;

import com.jege.hibernate.util.HibernateUtils;

/**
 * @author JE哥
 * @email 1272434821@qq.com
 * @description:雙向多對(duì)一的處理
 */
public class TwoCrudTest {
  // 單個(gè)保存:一次性保存1個(gè)部門(mén)筝闹,保存3個(gè)jege
  // 在單向多對(duì)一保存的時(shí)候需要先保存一方媳叨,不是會(huì)出現(xiàn)多余的update語(yǔ)句腥光,影響性能
  @Before
  public void before() throws Exception {
    Dept dept = new Dept();
    dept.setName("jege部門(mén)");

    // 傳入dept的本質(zhì)是處理數(shù)據(jù)庫(kù)user表的dept_id外鍵
    User user1 = new User("jegea", dept);
    User user2 = new User("jegeb", dept);

    Session session = HibernateUtils.INSTANCE.getSession();
    session.beginTransaction();

    System.out.println("保存之前:" + dept);
    session.save(dept);// Hibernate會(huì)自動(dòng)把保存后的主鍵放到當(dāng)前對(duì)象的id里面
    System.out.println("保存之后:" + dept);
    session.save(user1);
    session.save(user2);

    session.getTransaction().commit();
    session.close();
  }

  // 級(jí)聯(lián)保存:一行save方法保存3條數(shù)據(jù)(必須建立2方的關(guān)系)
  // 修改Dept.hbm.xml
  // <set name="users" inverse="true" cascade="save-update">
  // 一次性保存:一個(gè)部門(mén),在保存這個(gè)部門(mén)下面的2個(gè)jege
  @Test
  public void save() throws Exception {
    Dept dept = new Dept();
    dept.setName("jege部門(mén)");

    User user1 = new User("jege1");
    User user2 = new User("jege2");

    // 建立多方到一方的關(guān)系
    user1.setDept(dept);
    user2.setDept(dept);

    // 建立一方到多方的關(guān)系
    dept.getUsers().add(user1);
    dept.getUsers().add(user2);

    Session session = HibernateUtils.INSTANCE.getSession();
    session.beginTransaction();

    session.save(dept);// 持久化狀態(tài)

    session.getTransaction().commit();
    session.close();
  }

  // 級(jí)聯(lián)刪除:把一方和多方同時(shí)刪除:會(huì)出現(xiàn)3條delete語(yǔ)句
  // 修改Dept.hbm.xml<set name="users" inverse="true" cascade="all">
  @Test
  public void delete() throws Exception {
    Session session = HibernateUtils.INSTANCE.getSession();
    session.beginTransaction();
    session.delete(session.get(Dept.class, 1L));
    session.getTransaction().commit();
    session.close();
  }

  // 只刪除一方糊秆,不希望刪除一方包含的多方(可以先把多方的外鍵設(shè)置為null)
  // 方式1:修改Dept.hbm.xml<set name="users" inverse="true">
  @Test
  public void delete2() throws Exception {
    Session session = HibernateUtils.INSTANCE.getSession();
    session.beginTransaction();
    Dept dept = (Dept) session.get(Dept.class, 1L);// 持久化狀態(tài)
    Set<User> users = dept.getUsers();// 持久化狀態(tài)
    for (User user : users) {
      user.setDept(null);// 出現(xiàn)臟數(shù)據(jù)
    }
    session.delete(dept);
    session.getTransaction().commit();// 有事務(wù)武福,自動(dòng)更新臟數(shù)據(jù),發(fā)出update語(yǔ)句
    session.close();
  }

  // <set name="users" inverse="true">
  // 方式2:寫(xiě)類(lèi)似dml的hql來(lái)刪除
  @Test
  public void delete3() throws Exception {
    Long deptLong = 1L;
    Session session = HibernateUtils.INSTANCE.getSession();
    session.beginTransaction();

    // 1.先把多方的外鍵set null
    String hql = "update User set dept=null where dept.id=?";
    Query query = session.createQuery(hql);
    query.setLong(0, deptLong);
    System.out.println("受影響的行數(shù):" + query.executeUpdate());

    // 2.刪除一方
    hql = "delete from Dept where id=?";
    query = session.createQuery(hql);
    query.setLong(0, deptLong);
    System.out.println("受影響的行數(shù):" + query.executeUpdate());

    session.getTransaction().commit();
    session.close();
  }

  // 方式1:在多方刪除:先獲取多方痘番,然后刪除多方
  @Test
  public void delete4() throws Exception {
    Session session = HibernateUtils.INSTANCE.getSession();
    session.beginTransaction();
    User user = (User) session.get(User.class, 1L);// 持久化狀態(tài)
    session.delete(user);
    session.getTransaction().commit();
    session.close();
  }

  // 方式2:在一方刪除多方:獲取一方捉片,通過(guò)一方來(lái)刪除一條多方
  // 修改Dept.hbm.xml,實(shí)現(xiàn)級(jí)聯(lián)刪除解除關(guān)系的orphan兒子
  // <set name="users" inverse="true" cascade="delete-orphan">
  @Test
  public void delete5() throws Exception {
    Session session = HibernateUtils.INSTANCE.getSession();
    session.beginTransaction();
    Dept dept = (Dept) session.get(Dept.class, 1L);// 持久化狀態(tài)
    User user = (User) session.get(User.class, 2L);// 持久化狀態(tài)
    // 持久化狀態(tài)dept.getUsers()
    dept.getUsers().remove(user);
    session.getTransaction().commit();// 有事務(wù),自動(dòng)臟數(shù)據(jù)更新
    session.close();
  }

}

源碼地址

https://github.com/je-ge/hibernate

如果覺(jué)得我的文章或者代碼對(duì)您有幫助,可以請(qǐng)我喝杯咖啡汞舱。
**您的支持將鼓勵(lì)我繼續(xù)創(chuàng)作!謝謝伍纫! **

微信打賞
微信打賞

支付寶打賞
支付寶打賞

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市昂芜,隨后出現(xiàn)的幾起案子莹规,更是在濱河造成了極大的恐慌,老刑警劉巖说铃,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件访惜,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡腻扇,警方通過(guò)查閱死者的電腦和手機(jī)债热,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)幼苛,“玉大人窒篱,你說(shuō)我怎么就攤上這事〔把兀” “怎么了墙杯?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)括荡。 經(jīng)常有香客問(wèn)我高镐,道長(zhǎng),這世上最難降的妖魔是什么畸冲? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任嫉髓,我火速辦了婚禮,結(jié)果婚禮上邑闲,老公的妹妹穿的比我還像新娘算行。我一直安慰自己,他們只是感情好苫耸,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布州邢。 她就那樣靜靜地躺著,像睡著了一般褪子。 火紅的嫁衣襯著肌膚如雪量淌。 梳的紋絲不亂的頭發(fā)上骗村,一...
    開(kāi)封第一講書(shū)人閱讀 49,046評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音类少,去河邊找鬼叙身。 笑死,一個(gè)胖子當(dāng)著我的面吹牛硫狞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播晃痴,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼残吩,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了倘核?” 一聲冷哼從身側(cè)響起泣侮,我...
    開(kāi)封第一講書(shū)人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎紧唱,沒(méi)想到半個(gè)月后活尊,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡漏益,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年蛹锰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绰疤。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡铜犬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出轻庆,到底是詐尸還是另有隱情癣猾,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布余爆,位于F島的核電站纷宇,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蛾方。R本人自食惡果不足惜像捶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望转捕。 院中可真熱鬧作岖,春花似錦、人聲如沸五芝。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)枢步。三九已至沉删,卻和暖如春渐尿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背矾瑰。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工砖茸, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人殴穴。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓凉夯,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親采幌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子劲够,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容