主要讲解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. Java 集合 散列表hash table

    Java 集合 散列表hash table @author ixenos 摘要:hash table用链表数组实现.解决散列表的冲突:开放地址法 和 链地址法(冲突链表方式) hash table 是 ...

  2. hdu_5878_I Count Two Three(预处理)

    题目链接:hdu_5878_I Count Two Three 题意: 给你一个n,让你找满足那个式子的不比n小的最小数 题解: 先上个预处理,然后二分查找就行 #include<bits/st ...

  3. Asp.NET路由管道处理过程 【重要】

    当ASP.NET处理请求时,路由管道主要由以下几个步骤组成: 1.UrlRoutingModule尝试使用RouteTable中注册的理由匹配当前请求: 2.如果RouteTable中有一个路由成功匹 ...

  4. ffmpeg编译

    CFLAGS=-g ./configure --enable-opengl  --disable-yasm  --enable-shared --enable-pic

  5. hellobruce

  6. chapter 14_1 环境

    Lua将其所有的全局变量保存在一个常规的table中,称为“global environment”. Lua将环境table自身保存在一个全局变量_G中,_G._G等于 _G . 比如下面的代码打印出 ...

  7. 带宽 VS CDN (转载)

    并发的影响因素:带宽.web server(含php).static server.数据库 带宽价格: 静态IP企业宽带 5M 10M 50M 100M 200M 盛大云 华东双线 216/月 396 ...

  8. onmousedown活用之碰撞效果

    通过绝对定位,在页面中随意位置设置两个div; 也就是说div 是拖动的框,div1和div2是被触碰的框; <!DOCTYPE html> <html> <head&g ...

  9. SQL STUFF函数 拼接字符串

    今日看到一篇文章,是关于和并列的,也研究了下,还是不错的 要这种效果. create table tb(idint, value varchar(10)) insert into tbvalues(1 ...

  10. Qt主窗体显示最前

    在delphi中使用Application.BringToFront;可以保证当前程序显示在最前. 然而今天在Qt中,没有类似函数供调用. 尝试了activeWindow,show,showNorma ...