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 ...
随机推荐
- 设计新Xlator扩展GlusterFS[转]
原文:http://www.linuxidc.com/Linux/2013-08/89105.htm 1. GlusterFS概述 GlusterFS是一个开源的分布式文件系统,具有强大的Scale- ...
- windows网络编程(1)同步套接字
1.socket是应用程序与网络驱动程序的桥梁,在应用程序中创建socket,将数据交付给socket即完成数据传输,剩下的任务由socket和网络驱动程序完成: 2.套接字类型:SOCK_STREA ...
- 5、判断、循环、数组综合练习案例(迷你DVD)
迷你dvd代码如下: package com.manager; import java.util.Scanner; public class DVDManage { public static voi ...
- linux 移除svn文件夹
find . -name .svn -type d -exec rm -fr {} \;
- FZU 2086 餐厅点餐
好久不写博客了……得有快一个月了……看到大神们一篇篇博文 唉……差好多……这一个月 有蓝桥杯还有校赛……校赛签到题都没签完 实力铁牌……不过蓝桥杯一等奖 五月份帝都之行还挺令人期待……清明小长假之前 ...
- digitalocean网站打不开,大陆无法正常访问怎么办?
在中国大陆,由于某些恶心的原因,digitalocean官方网站经常出现无法打开,或者打开后网页异常的情况,如果你是一个新注册用户,你甚至会被吓到,一个全球知名的vps主机商网站可能是这样的: 我的天 ...
- if语句—交互程序二
参考:<笨方法学Python>—习题31 用了两个嵌套的if语句! # coding: utf-8 print u"欢迎来到玩家国度, 你需要根据提示完成闯关!" # ...
- js 禁止重复提交
/*分享按钮*/ var flag = true; $(".recommed a").click(function() { if (flag == true) { getServe ...
- 用Jedis获取redis连接(集群和非集群状态下)
第一:非集群状态下 非集群状态下用Jedis获取redis连接,得到Jedis对象即可,一共有两种: 1.利用Jedis构造器,仅限用于测试,在实际项目中肯定是用JedisPool. Jedis(St ...
- wordpress建站过程2——结构
开始wordpress之前,我们需要了解,wordpress的结构和调用方式. 当一个wordpress开始之后,他会读取[当前主题]的index.php.所以一旦主题切换了,它读的就是其他主题的in ...