主要讲解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. 浙江大学 pat 1006题解

    1006. Sign In and Sign Out (25) 时间限制 400 ms 内存限制 32000 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue ...

  2. python Asyncore.dispatcher 理解

    1.Asyncore是python的标准库.Asyncore.dispatcher 是这个库中的一个socket的框架,为socket添加了一些通用的回调方法,比如: def listen(self, ...

  3. SERVICE_USE_PID

    openwrt中启动脚本中经常出现如下一句: SERVICE_USE_PID=1 例如 lldp启动脚本 lldpd.init中如下: #!/bin/sh /etc/rc.common # Copyr ...

  4. Qt5 Cmake

    project(my) cmake_minimum_required(VERSION ) set (CMAKE_PREFIX_PATH "C:\\Qt\\Qt5.3.0\\5.3\\msvc ...

  5. 【Echarts每天一例】-1

    官方网址:http://echarts.baidu.com/doc/example/line1.html 使用百度echarts官方实例:http://ask.csdn.net/questions/1 ...

  6. CentOS 7 多网卡绑定

    根据官方文档Red_Hat_Enterprise_Linux-7-Networking_Guide-en-US用nmcli做起来还是相当容易的.下面把俺的步骤贴下. 1.查看目前网卡的名称和状态.#n ...

  7. 工作中用到的简单linux命令

    1.rpm包查询.卸载.安装: rpm包查询 rpm -q 包名(不带版本号.后缀等)  q----query rpm包卸载 rpm -e 包名(不带版本号.后缀等)e----erase rpm包安装 ...

  8. ios UITapGestureRecognizer 单指单击、单指多击、多指单击、多指多击事件操作

    转自:http://blog.csdn.net/longzs/article/details/7457108 在ios开发中,需用到对于手指的不同操作,以手指点击为例:分为单指单击.单指多击.多指单击 ...

  9. 利用Ajax实现前端与.net后端实现数据交互

    使用场景和需求:用户在地址栏输入请求地址,先.net服务器发送页面请求,该页面包含Echart图表,在页面中向.net后端发送数据请求,获取数据后,将数据填充到Echart图表中.其中包含带参与不带参 ...

  10. 让NetBeans的Web应用热部署可用

    MyEclipse最大的优点是,开发web应用时,可以轻松地做到:修改Java类后,在浏览器中刷新页面立刻就可以看到修改的效果,不用手动重启Web Server. 但是MyEclipse除此之外其他方 ...