主要讲解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

如果觉得我的文章对您有帮助,请予以打赏。您的支持将鼓励我继续创作!谢谢!



Hibernate 系列教程5-双向多对一的更多相关文章

  1. Hibernate 系列教程6-双向多对多

    双向多对多inverse配置 如果关系两边都使用默认inverse=false配置,表示关系两边都可以管理中间表的数据 关系其中一边设置inverse=true配置,表示自己放弃管理中间表关系,由对方 ...

  2. Hibernate 系列教程4-单向多对一

    项目图片 hibernate.cfg.xml <mapping resource="com/jege/hibernate/one/way/manytoone/User.hbm.xml& ...

  3. JPA 系列教程7-双向多对多

    双向多对多的ddl语句 同单向多对多表的ddl语句一致 Student package com.jege.jpa.many2many; import java.util.HashSet; import ...

  4. JPA 系列教程3-单向多对一

    JPA中的@ManyToOne 主要属性 - name(必需): 设定"many"方所包含的"one"方所对应的持久化类的属性名 - column(可选): 设 ...

  5. Hibernate 系列教程16-二级缓存

    pom.xml <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate- ...

  6. Hibernate 系列教程9-自关联

    自关联:本质还是原来双向一对多,原来要配置两个类,现在全部都配置在一个类里面 Employee public class Employee { private Long id; private Str ...

  7. Hibernate 系列教程7-双向一对一

    双向一对一 一对一主要用在 一个一方需要的信息比较少,比如注册的登录信息 另一个一方存储的信息比较多,比如注册之后用户填写的详细信息 实现方式常用的主要有2种: java模型都是一样,其中一个映射文件 ...

  8. JPA 系列教程6-单向多对多

    JPA中的@ManyToMany @ManyToMany注释表示模型类是多对多关系的一端. @JoinTable 描述了多对多关系的数据表关系. name 属性指定中间表名称 joinColumns ...

  9. Hibernate 系列教程17-查询缓存

    在二级缓存配置成功的基础上进行查询缓存配置 Product public class Product { private Long id; private String name; Product.h ...

随机推荐

  1. 【Python@Thread】thread模块

    一.关于Python多线程 Python解释器中可以同时运行多个线程,但是再任意时刻只能有一个线程在解释器运行. Python虚拟机的访问是由全局解锁器(GIL)控制的,由GIL保证同时只有一个线程的 ...

  2. PHP验证码程序

    [摘自网络,参考学习] <?php/** * vCode(m,n,x,y) m个数字 显示大小为n 边宽x 边高y * http://blog.qita.in * 自己改写记录session $ ...

  3. Lucene基础(2)

    上一篇:Lucene基础(1) 一.Lucene术语 Document, Field, Term, Query, Analyzer相信在其中大多数在之前已经理解了...对其中部分概念详细说明 Docu ...

  4. 转载–移动互联网终端的touch事件,touchstart, touchend, touchmove

    转载请注明: 转载自WEB前端开发(www.css119.com)-关注常见的WEB前端开发问题.最新的WEB前端开发技术(webApp开发.移动网站开发).最好的WEB前端开发工具和最全的WEB前端 ...

  5. idea 注册码

    生成地址:http://idea.lanyus.com/ ------------------------------------- IntelliJ IDEA 注册码 *.lanyus.com及*. ...

  6. OC之消息基本概念

    要说清楚消息这个话题,我们必须先来了解三个概念 Class, SEL, IMP,它们在 objc/objc.h 中定义: typedef struct objc_class *Class; typed ...

  7. for、while循环的洪荒之力

    在python里,如果说print语句是用得最多的话,那么,要我说,除了for语句,谁都不敢认老二. 下面,让我们来看看for语句能搞出什么花样 1. 计时(无限次数) 说到计时,我们先来试下显示当前 ...

  8. 关于oracle数据库(6)约束

    约束类型 1.主键primary key(一般是一个表的标志,所以一个表只能有一个主键:主键不能为空,不能重复) 2.唯一键unique(不能重复) 3.外键foreign key 4.检查约束che ...

  9. linux下写脚本时-gt是什么意思

    -eq 等于-ne 不等于-gt 大于-ge 大于等于-lt 小于-le 小于等于

  10. mybatis 一点整理

    mapper指定对应的接口 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper ...