例:一个班级可以有多个学生,而一个学生只能属于一个班级。
准备
POJO
// 班级:com.zze.bean.Class
package com.zze.bean;
import java.util.HashSet;
import java.util.Set;
public class Class {
private Integer id;
private String name;
private Set<Student> students = new HashSet<>();
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<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
}
// 学生:com.zze.bean.Student
package com.zze.bean;
import java.util.Date;
public class Student {
private Integer id;
private String name;
private Integer age;
private Date birthday;
private String address;
private Class clazz;
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 Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Class getClazz() {
return clazz;
}
public void setClazz(Class clazz) {
this.clazz = clazz;
}
}
配置文件
<!-- com/zze/bean/Class.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>
<class name="com.zze.bean.Class" table="class">
<id name="id">
<generator class="native"/>
</id>
<property name="name" length="32"/>
<!--
set :
name : ‘多’的一方在当前类中的属性名
-->
<set name="students">
<!--
key :
column : 外键表中的关联当前类对应表的外键名称
-->
<key column="cid"/>
<!--
one-to-many : 标识一对多关系
class : ‘多’的一方全限定类名
-->
<one-to-many class="com.zze.bean.Student"/>
</set>
</class>
</hibernate-mapping>
<!-- com/zze/bean/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>
<class name="com.zze.bean.Student" table="student">
<id name="id">
<generator class="native"/>
</id>
<property name="name" length="32"/>
<property name="age"/>
<property name="birthday"/>
<property name="address"/>
<!--
many-to-one : 标识多对一关系
name : ‘一’的一方在当前类中属性名
column : 外键名称
class : ‘一’的一方的全限定类名
-->
<many-to-one name="clazz" column="cid" class="com.zze.bean.Class"/>
</class>
</hibernate-mapping>
<!-- 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="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://192.168.208.153:3306/test</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<property name="current_session_context_class">thread</property>
<property name="hibernate.hbm2ddl.auto">create</property>
<mapping resource="com/zze/bean/Class.hbm.xml"></mapping>
<mapping resource="com/zze/bean/Student.hbm.xml"></mapping>
</session-factory>
</hibernate-configuration>
使用
普通操作
例 1:两方关联,保存两方 - 新建一个班级,新建两个学生,班级主动关联学生,学生也主动关联班级,保存班级,再保存学生,成功。
Session session = HibernateUtil.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 创建一个班级
Class clazz = new Class();
clazz.setName("1班");
// 创建两个学生
Student student1 = new Student();
student1.setName("张三");
Student student2 = new Student();
student2.setName("李四");
// 让班级关联学生
clazz.getStudents().add(student1);
clazz.getStudents().add(student2);
// 让学生关联班级
student1.setClazz(clazz);
student2.setClazz(clazz);
// 保存班级
session.save(clazz);
// 保存学生
session.save(student1);
session.save(student2);
transaction.commit();
例 2:两方关联,保存一方 - 新建一个班级,新建两个学生,班级主动关联学生,学生也主动关联班级,只保存班级,异常,需使用下面的级联保存。
Session session = HibernateUtil.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 创建一个班级
Class clazz = new Class();
clazz.setName("1班");
// 创建两个学生
Student student1 = new Student();
student1.setName("张三");
Student student2 = new Student();
student2.setName("李四");
// 让班级关联学生
clazz.getStudents().add(student1);
clazz.getStudents().add(student2);
// 让学生关联班级
student1.setClazz(clazz);
student2.setClazz(clazz);
// 保存班级
session.save(clazz);
transaction.commit();
/*
抛异常:org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.zze.bean.Student
原因是:保存班级时,班级关联的学生为瞬时态对象,不能与瞬时态对象建立关系。
*/
级联操作
级联指的是操作一个对象的时候,是否会同时操作其关联的对象。
级联的方向性:
- 操作一的一方的时候,是否会同时操作到多的一方。
- 操作多的一方的时候,是否会同时操作到一的一方。
级联保存或更新
例 3:‘一’方关联,保存‘一’方 - 新建一个班级,新建两个学生,班级主动关联学生,只保存班级,级联保存了学生,成功。
<!-- com/zze/bean/Class.hbm.xml:修改‘一’(班级)的映射文件,在 set 标签中添加属性 cascade="save-update" -->
<?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>
<class name="com.zze.bean.Class" table="class">
<id name="id">
<generator class="native"/>
</id>
<property name="name" length="32"/>
<set name="students" cascade="save-update">
<key column="cid"/>
<one-to-many class="com.zze.bean.Student"/>
</set>
</class>
</hibernate-mapping>
Session session = HibernateUtil.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 创建一个班级
Class clazz = new Class();
clazz.setName("1班");
// 创建两个学生
Student student1 = new Student();
student1.setName("张三");
Student student2 = new Student();
student2.setName("李四");
// 让班级关联学生
clazz.getStudents().add(student1);
clazz.getStudents().add(student2);
// 保存班级级联保存学生
session.save(clazz);
transaction.commit();
例 4:‘多’方关联,保存‘多’方 - 新建一个班级,新建两个学生,学生主动关联班级,只保存学生,级联保存了班级,成功。
<!-- com/zze/bean/Student.hbm.xml:修改‘多’(学生)的映射文件,在 many-to-one 标签中添加属性 cascade="save-update" -->
<?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>
<class name="com.zze.bean.Student" table="student">
<id name="id">
<generator class="native"/>
</id>
<property name="name" length="32"/>
<property name="age"/>
<property name="birthday"/>
<property name="address"/>
<many-to-one name="clazz" column="cid" class="com.zze.bean.Class" cascade="save-update"/>
</class>
</hibernate-mapping>
Session session = HibernateUtil.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 创建一个班级
Class clazz = new Class();
clazz.setName("1班");
// 创建两个学生
Student student1 = new Student();
student1.setName("张三");
Student student2 = new Student();
student2.setName("李四");
// 让学生关联班级
student1.setClazz(clazz);
student2.setClazz(clazz);
// 保存学生级联保存班级
session.save(student1);
session.save(student2);
transaction.commit();
级联删除
假如表中已有如下数据:
例 5:删除‘一’级联删除‘多’ - 删除班级,级联删除该班级下所有学生。
<!-- com/zze/bean/Class.hbm.xml:修改‘一’(班级)的映射文件,在 set 标签中添加属性 cascade="delete" -->
<?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>
<class name="com.zze.bean.Class" table="class">
<id name="id">
<generator class="native"/>
</id>
<property name="name" length="32"/>
<set name="students" cascade="save-update,delete">
<key column="cid"/>
<one-to-many class="com.zze.bean.Student" />
</set>
</class>
</hibernate-mapping>
Session session = HibernateUtil.getCurrentSession();
Transaction transaction = session.beginTransaction();
Class clazz = session.get(Class.class, 1);
session.delete(clazz);
transaction.commit();
例 6:删除‘多’级联删除‘一’ - 删除学生,级联删除该学生所属班级。
<!-- com/zze/bean/Student.hbm.xml:修改‘多’(学生)的映射文件,在 many-to-one 标签中添加属性 cascade="delete" -->
<?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>
<class name="com.zze.bean.Student" table="student">
<id name="id">
<generator class="native"/>
</id>
<property name="name" length="32"/>
<property name="age"/>
<property name="birthday"/>
<property name="address"/>
<many-to-one name="clazz" column="cid" class="com.zze.bean.Class" cascade="save-update,delete"/>
</class>
</hibernate-mapping>
Session session = HibernateUtil.getCurrentSession();
Transaction transaction = session.beginTransaction();
Student student = session.get(Student.class, 1);
session.delete(student);
transaction.commit();
// 级联删除‘一’的一方,将其它关联‘一’的一方的数据的外键设为 null。
// 如果‘一’的一方也设置了级联删除,那么所有关联‘一’的一方的数据都会被删除。
评论区