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
如果觉得我的文章对您有帮助,请予以打赏。您的支持将鼓励我继续创作!谢谢!
Hibernate 系列教程5-双向多对一的更多相关文章
- Hibernate 系列教程6-双向多对多
双向多对多inverse配置 如果关系两边都使用默认inverse=false配置,表示关系两边都可以管理中间表的数据 关系其中一边设置inverse=true配置,表示自己放弃管理中间表关系,由对方 ...
- Hibernate 系列教程4-单向多对一
项目图片 hibernate.cfg.xml <mapping resource="com/jege/hibernate/one/way/manytoone/User.hbm.xml& ...
- JPA 系列教程7-双向多对多
双向多对多的ddl语句 同单向多对多表的ddl语句一致 Student package com.jege.jpa.many2many; import java.util.HashSet; import ...
- JPA 系列教程3-单向多对一
JPA中的@ManyToOne 主要属性 - name(必需): 设定"many"方所包含的"one"方所对应的持久化类的属性名 - column(可选): 设 ...
- Hibernate 系列教程16-二级缓存
pom.xml <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate- ...
- Hibernate 系列教程9-自关联
自关联:本质还是原来双向一对多,原来要配置两个类,现在全部都配置在一个类里面 Employee public class Employee { private Long id; private Str ...
- Hibernate 系列教程7-双向一对一
双向一对一 一对一主要用在 一个一方需要的信息比较少,比如注册的登录信息 另一个一方存储的信息比较多,比如注册之后用户填写的详细信息 实现方式常用的主要有2种: java模型都是一样,其中一个映射文件 ...
- JPA 系列教程6-单向多对多
JPA中的@ManyToMany @ManyToMany注释表示模型类是多对多关系的一端. @JoinTable 描述了多对多关系的数据表关系. name 属性指定中间表名称 joinColumns ...
- Hibernate 系列教程17-查询缓存
在二级缓存配置成功的基础上进行查询缓存配置 Product public class Product { private Long id; private String name; Product.h ...
随机推荐
- jQuery技巧大放送【转】
1.关于页面元素的引用 通过jquery的$()引用元素包括通过id.class.元素名以及元素的层级关系及dom或者xpath条件等方法,且返回的对象为jquery对象(集合对象),不能直接调用do ...
- lua中获取时间
os.date() 返回 XX/XX/XX XX:XX:XX 月/日/年 时:分:秒 os.time() 返回的是从1970年1月1日到现在的经过的秒数. 例如: print(os. ...
- delphi学习treeview中从表列名和数据添加为目录并双击自动选中
1 unit Unit2; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, Syst ...
- .Net Core 中使用AutoMapper
1.新建一个类 using AutoMapper; using YourModels; using YourViewModels; namespace YourNamespace { public c ...
- 直接粘贴代码到网络上:command-line pastebins
软件作用 直接把管道里面的文字内容传到网站上面,然后反馈一个地址可以读取内容. 同类软件 wgetpaste dpaste pastebin pasteie 用法 介绍wgetpaste为例: GEN ...
- BASE1(matlab)
version memory clc clear tab键 F5键 运行m文件 F9键 只运行选中的 Ctrl+R 注释 Ctrl+T 反注释 Ctrl+I 格式化代码 edit xxx. ...
- Openjudge-计算概论(A)-分数求和
描述: 输入n个分数并对他们求和,并用最简形式表示.所谓最简形式是指:分子分母的最大公约数为1:若最终结果的分母为1,则直接用整数表示. 如:5/6.10/3均是最简形式,而3/6需要化简为1/2, ...
- robotframework代码定位感悟
robotframework代码定位感悟: 在做自动化的时候,有时候还是要考虑真实的操作,考虑人为反应,网络,页面渲染,服务器处理请求的过程及数据是否真实到达响应的位置, 不能一味的按照程序的速度 去 ...
- yii2.0图片上传
在根目录下夹uploads文件夹 控制器 UploadController.php <?php namespace frontend\controllers; use Yii; use fron ...
- mongodb type it for more
当使用MongoChef Core 链接mongodb的时候 ,需要查看更多的数据时候,系统提示 type it for more 可以设置系统参数 DBQuery.shellBatchSize = ...