Hibernate中一对多的相关操作
什么叫做级联操作?
级联操作指的是,操作一个对象的时候,会同时操作其关联的对象。
级联是有方向性:
操作一的一方的时候,是否操作到多的一方。
操作多的一方的时候,是否操作到一的一方。
1、级联保存更新
测试代码1:
package com.pipi.hibernate03;
import myutils.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.Transaction;
/*
只对Dept.hbm.xml进行级联保存更新配置
在Dept.hbm.xml中配置,为set标签加个cascade属性,值为save-update
<set name="emps" cascade="save-update">
此时Emp.hbm.xml中并没有设置cascade属性。
*/
public class Test02 {
public static void main(String[] args) {
Session session = HibernateUtil.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 创建1个部门
Dept dept = new Dept(50, "皮皮部门", "北京");
// 创建2个员工
Emp emp1 = new Emp();
emp1.setEname("张三");
Emp emp2 = new Emp();
emp2.setEname("李四");
// 将部门与员工关联,此时只配置了Dept.hbm.xml级联保存更新
emp1.setDept(dept);
emp2.setDept(dept);
dept.getEmps().add(emp1);
dept.getEmps().add(emp2);
// 只保存部门dept
session.save(dept);
transaction.commit();
}
}
测试代码2:
package com.pipi.hibernate03;
import myutils.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.Transaction;
/*
只对Emp.hbm.xml进行级联保存更新配置
在many-to-one标签中进行设置
<many-to-one name="dept" cascade="save-update" class="com.pipi.hibernate03.Dept" column="deptno"/>
此时Dept.hbm.xml中并没有配置cascade属性
*/
public class Test03 {
public static void main(String[] args) {
Session session = HibernateUtil.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 创建1个部门
Dept dept = new Dept(50, "皮皮部门", "北京");
// 创建2个员工
Emp emp1 = new Emp();
emp1.setEname("张三");
Emp emp2 = new Emp();
emp2.setEname("李四");
// 设置关联,此时只对Emp.hbm.xml进行了级联保存配置
emp1.setDept(dept);
emp2.setDept(dept);
dept.getEmps().add(emp1);
dept.getEmps().add(emp2);
// 只保存员工
session.save(emp1);
session.save(emp2);
transaction.commit();
}
}
测试代码3:
package com.pipi.hibernate03;
import myutils.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.Transaction;
// Dept.hbm.xml,Emp.hbm.xml映射文件都配置了:级联保存更新
// 对象导航测试
public class Test04 {
public static void main(String[] args) {
Session session = HibernateUtil.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 创建1个部门
Dept dept = new Dept(50, "皮皮部门", "北京");
// 创建2个员工
Emp emp1 = new Emp();
emp1.setEname("张三");
Emp emp2 = new Emp();
emp2.setEname("李四");
// 注意:这里只设置为,单向关联
emp1.setDept(dept);
dept.getEmps().add(emp2);
// 只执行下面任意一条语句
//session.save(emp1); // 会发送几条insert语句? 答:3条
//session.save(dept); // 会发送几条insert语句? 答:2条
session.save(emp2); // 会发送几条insert语句? 答:1条
transaction.commit();
}
}
2、级联删除
测试代码:
package com.pipi.hibernate03;
import myutils.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.Transaction;
/*
在部门映射文件Dept.hbm.xml中的set标签中配置cascade属性,值为delete
如果原来的级联属性有值,可以继续添加,用逗号隔开即可
<set name="emps" cascade="save-update, delete">
*/
// 级联删除:删除一个部门,级联删除该部门的所有员工
public class Test05 {
public static void main(String[] args) {
Session session = HibernateUtil.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 默认的情况,没有配置级联删除
Dept dept = session.get(Dept.class, 50);
//session.delete(dept); // 会先将该部门的所有员工的部门外键值设置为null,再删除该部门
// 配置了级联删除
session.delete(dept); // 删除部门,同时级联删除该部门的所有员工
transaction.commit();
}
}
/*
Hibernate中也可以删除一个员工,同时把部门级联删除。
只不过这种需求是不合理的。很少用到。
*/
3、一对多设置了双向关联产生多余的SQL语句
测试代码:
package com.pipi.hibernate03;
import myutils.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.Transaction;
/*
一对多关系,设置双向关联,将会产生多余的sql语句执行。如何解决?
让一的一方放弃外键管理。在Dept.hbm.xml映射文件中的set标签中配置inverse属性
<set name="emps" cascade="save-update, delete" inverse="true">
*/
// 将7955员工的部门编号改为40部门
public class Test06 {
public static void main(String[] args) {
Session session = HibernateUtil.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 获取7955号员工
Emp emp = session.get(Emp.class, 7955);
// 获取40部门
Dept dept = session.get(Dept.class, 40);
// 设置双向关联
emp.setDept(dept);
dept.getEmps().add(emp);
// 手动更新,当然持久态的对象改变会自动更新数据库
session.update(emp);
transaction.commit();
}
}
解决多余的SQL语句
- 单向维护:
- 使一方放弃外键维护权:
一的一方放弃。在set上配置inverse=”true” - 一对多的关联查询的修改的时候。(CRM练习)
4、区分cascade 和 inverse
测试代码:
package com.pipi.hibernate03;
import myutils.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.Transaction;
// 区分cascade, inverse的区别
public class Test07 {
public static void main(String[] args) {
Session session = HibernateUtil.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 创建1个部门
Dept dept = new Dept(50, "皮皮部门", "北京");
// 创建1个员工
Emp emp = new Emp();
emp.setEname("张三");
// 设置关联
dept.getEmps().add(emp);
// 前提:Dept.hbm.xml中配置了:cascade为save-update,inverse为true。
session.save(dept);
// 请问数据库中保存的信息是怎样的?
// 部门50会插入到数据库中,张三员工也会插入到数据库中,张三的外键部门为null。
transaction.commit();
}
}