Hibernate 菜鸟教程 5 双向多对一

主要讲解inverse和cascade的用法

cascade定义的是关系两端对象到对象的级联关系;
而inverse定义的是关系和对象的级联关系(管理外键的值)。

inverse

属性默认是false的,就是说关系的两端都来维护关系。
在双向多对一里面配置到一方的集合属性上面,inverse=true,表示关系的维护(外键的值)由对方(多方)来管理

cascade

all : 所有情况下均进行关联操作。
none:所有情况下均不进行关联操作。这是默认值。
save-update:在执行save/update/saveOrUpdate时进行关联操作。
delete:在执行delete时进行关联操作。
delete-orphan:删除解除关系的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>

测试类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:双向多对一的处理
 */
public class TwoCrudTest {
  // 单个保存:一次性保存1个部门,保存3个jege
  // 在单向多对一保存的时候需要先保存一方,不是会出现多余的update语句,影响性能
  @Before
  public void before() throws Exception {
    Dept dept = new Dept();
    dept.setName("jege部门");

    // 传入dept的本质是处理数据库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会自动把保存后的主键放到当前对象的id里面
    System.out.println("保存之后:" + dept);
    session.save(user1);
    session.save(user2);

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

  // 级联保存:一行save方法保存3条数据(必须建立2方的关系)
  // 修改Dept.hbm.xml
  // <set name="users" inverse="true" cascade="save-update">
  // 一次性保存:一个部门,在保存这个部门下面的2个jege
  @Test
  public void save() throws Exception {
    Dept dept = new Dept();
    dept.setName("jege部门");

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

    // 建立多方到一方的关系
    user1.setDept(dept);
    user2.setDept(dept);

    // 建立一方到多方的关系
    dept.getUsers().add(user1);
    dept.getUsers().add(user2);

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

    session.save(dept);// 持久化状态

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

  // 级联删除:把一方和多方同时删除:会出现3条delete语句
  // 修改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();
  }

  // 只删除一方,不希望删除一方包含的多方(可以先把多方的外键设置为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);// 持久化状态
    Set<User> users = dept.getUsers();// 持久化状态
    for (User user : users) {
      user.setDept(null);// 出现脏数据
    }
    session.delete(dept);
    session.getTransaction().commit();// 有事务,自动更新脏数据,发出update语句
    session.close();
  }

  // <set name="users" inverse="true">
  // 方式2:写类似dml的hql来删除
  @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("受影响的行数:" + query.executeUpdate());

    // 2.删除一方
    hql = "delete from Dept where id=?";
    query = session.createQuery(hql);
    query.setLong(0, deptLong);
    System.out.println("受影响的行数:" + 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);// 持久化状态
    session.delete(user);
    session.getTransaction().commit();
    session.close();
  }

  // 方式2:在一方删除多方:获取一方,通过一方来删除一条多方
  // 修改Dept.hbm.xml,实现级联删除解除关系的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);// 持久化状态
    User user = (User) session.get(User.class, 2L);// 持久化状态
    // 持久化状态dept.getUsers()
    dept.getUsers().remove(user);
    session.getTransaction().commit();// 有事务,自动脏数据更新
    session.close();
  }

}

源码地址

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

如果觉得我的文章或者代码对您有帮助,可以请我喝杯咖啡。
**您的支持将鼓励我继续创作!谢谢! **

微信打赏
微信打赏

支付宝打赏
支付宝打赏

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容