作者:指尖青春_388 | 来源:互联网 | 2023-06-21 10:48
Hibernate关系映射-级联操作cascade在双向一对多的学习中,我们发现每次保存对象时,学生对象和年纪对象都需要我们持久化之session,既然它们两者有关联关系,可不可以
Hibernate关系映射-级联操作cascade
在双向一对多的学习中,我们发现每次保存对象时,学生对象和年纪对象都需要我们持久化之session,既然它们两者有关联关系,可不可以只持久化其中一端,另一端就会自动的被持久化呢,这个属性就是Hibernate的cascade。cascade是多对一、一对多、一对一、多对多各种关系之间的一种级联操作行为。(关键语句:cascade="save-update"。)
一、什么是级联操作
官方解释:必须级联到关联目标的操作,默认情况下没有级联操作。
当Hibernate持久化一个瞬时对象时,在默认情况下,它不会自动持久化所关联的其他临时对象,而是会抛出org.hibernate.TransientObjectException。
级联的意思是:本实体做了什么事,也要拉上另一个关联的实体,导致另一个实体跟着做事情。就是说我删除了,你也必须删除!关联目标,指的是关联的那个实体 。
二、准备案例
在明确了级联操作的概念知识以后,使用学生表和年纪表的双向一对多关系,实现级联操作行为。
学生表和年纪表的双向一对多关系学习请参考(Hibernate关系映射-双向一对多)。
cascade级联操作,默认是none不级联。
none:不级联。
save-update:保存和更新某一端数据时,另一端数据可以一起保存和更新。
delete:删除级联-不能在多的一端使用。
all:表示所有操作都级联
三、实现级联操作
1、配置多端
编写配置文件
Student.hbm.xml
xml version="1.0" encoding="UTF-8" ?>
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.uestc">
<class name="Student">
<id name="id">
<generator class="native"/>
id>
<property name="name"/>
<property name="age"/>
<many-to-one cascade="save-update" name="grade" class="Grade"
column="grade_id" foreign-key="fk_grade"/>
class>
hibernate-mapping>
2.编写Grade.hbm.xml
xml version="1.0" encoding="UTF-8" ?>
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.uestc">
<class name="Grade">
<id name="id">
<generator class="native"/>
id>
<property name="name"/>
<set name="students" cascade="save-update">
<key foreign-key="fk_grade" column="grade_id">key>
<one-to-many class="Student"/>
set>
class>
hibernate-mapping>
Student类
public class Student implements Serializable {
private Integer id;
private String name;
private Integer age;
private Grade grade;
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", grade=" + grade +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Grade getGrade() {
return grade;
}
public void setGrade(Grade grade) {
this.grade = grade;
}
}
Grade类
public class Grade implements Serializable {
private Integer id;
private String name;
private Set students = new HashSet<>();
@Override
public String toString() {
return "Grade{" +
"id=" + id +
", name='" + name + '\'' +
", students=" + students +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set getStudents() {
return students;
}
public void setStudents(Set students) {
this.students = students;
}
}
编写hibernate.cfg.xml
xml version="1.0" encoding="utf-8" ?>
DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">com.mysql.jdbc.Driverproperty>
<property name="connection.url">jdbc:mysql:///hibernateproperty>
<property name="connection.username">rootproperty>
<property name="connection.password">rootproperty>
<property name="dialect">org.hibernate.dialect.MySQL8Dialectproperty>
<property name="hbm2ddl.auto">updateproperty>
<property name="show_sql">trueproperty>
<property name="format_sql">trueproperty>
<mapping resource="com/uestc/Grade.hbm.xml"/>
<mapping resource="com/uestc/Student.hbm.xml"/>
session-factory>
hibernate-configuration>
测试类
/**
* 单向多对一
*/
@Test
public void testSingleManyToOne() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
//创建实例对象
Grade grade1 = new Grade();
grade1.setName("基础");
Grade grade2 = new Grade();
grade2.setName("中级");
Student student = new Student();
student.setName("张三");
student.setAge(18);
student.setGrade(grade1);
Student student2 = new Student();
student2.setName("李四");
student2.setAge(18);
student2.setGrade(grade1);
Student student3 = new Student();
student3.setName("王五");
student3.setAge(18);
student3.setGrade(grade2);
//存储的顺序是根据外键约束而定的,如果外键不可以为空,必须先存储外键的一端
//如果外键可以为空,随意存储,但是建议先存储外键的一端,因为会多执行update
// session.save(grade1);
// session.save(grade2);
session.save(student);
session.save(student2);
session.save(student3);
tx.commit();
}catch (Exception e){
e.printStackTrace();
tx.rollback();
}finally {
HibernateUtil.closeSession();
}
}
/**
* 获取
* 查询不用开启事务,会降低性能
*/
@Test
public void testSingleGetManyToOne() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
Student student = session.get(Student.class,1);
System.out.println("stuName:" +student.getName() + ",grade:" +student.getGrade().getName());
tx.commit();
}catch (Exception e){
e.printStackTrace();
tx.rollback();
}finally {
HibernateUtil.closeSession();
}
}
/**
* 单向一对多
*/
@Test
public void testSingleOneToMany() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
//创建实例对象
Student student = new Student();
student.setName("张三");
student.setAge(18);
Student student2 = new Student();
student2.setName("李四");
student2.setAge(18);
Student student3 = new Student();
student3.setName("王五");
student3.setAge(18);
Grade grade1 = new Grade();
grade1.setName("基础");
grade1.getStudents().add(student);
grade1.getStudents().add(student2);
Grade grade2 = new Grade();
grade2.setName("中级");
grade2.getStudents().add(student3);
//存储的顺序是根据外键约束而定的,如果外键不可以为空,必须先存储外键的一端
//单向一对多会多执行update语句,效率不如多对一
session.save(grade1);
session.save(grade2);
// session.save(student);
// session.save(student2);
// session.save(student3);
tx.commit();
}catch (Exception e){
e.printStackTrace();
tx.rollback();
}finally {
HibernateUtil.closeSession();
}
}
/**
* 获取
* 查询不用开启事务,会降低性能
*/
@Test
public void testSingleGetOneToMany() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
Student student = session.get(Student.class,1);
System.out.println("stuName:" +student.getName() + ",grade:" +student.getGrade().getName());
System.out.println("---------------------分割线-------------------");
Grade grade = session.get(Grade.class,1);
System.out.println("grade:" +grade.getName());
for(Student stu : grade.getStudents()){
System.out.println("stuName:" +stu.getName());
}
tx.commit();
}catch (Exception e){
e.printStackTrace();
tx.rollback();
}finally {
HibernateUtil.closeSession();
}
}
四、总结
大家可以尝试除了新增以外的其他操作,可以得出以下结论