一、多对多关联关系映射
以 学生Student选课Course为例。
1、实体类编写和多对多配置映射配置
学生类:
package lsq.hibernate.manytomany;
import java.util.HashSet;
import java.util.Set;
//学生类
public class Student {
private Integer id;
private String sname;
private Set<Course> courses = new HashSet<Course>();
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Set<Course> getCourses() {
return courses;
}
public void setCourses(Set<Course> courses) {
this.courses = courses;
}
}
课程类:
package lsq.hibernate.manytomany;
import java.util.HashSet;
import java.util.Set;
//课程类
public class Course {
private Integer id;
private String cname;
private Set<Student> students = new HashSet<Student>();
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
}
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="lsq.hibernate.manytomany.Student" table="students" catalog="hibernate3day2">
<id name="id">
<generator class="identity"></generator>
</id>
<property name="sname"></property>
<!-- 多对多 -->
<!--
name:关联属性名
table:产生中间表表名
-->
<set name="courses" table="student_course">
<!-- 当前对象在中间表产生外键列名 -->
<key column="student_id"></key>
<!-- column指定集合对应表在中间表产生外键列名 -->
<many-to-many column="course_id" class="lsq.hibernate.manytomany.Course"></many-to-many>
</set>
</class>
</hibernate-mapping>
Course.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="lsq.hibernate.manytomany.Course" table="courses" catalog="hibernate3day2">
<id name="id">
<generator class="identity"></generator>
</id>
<property name="cname"></property>
<!-- 多对多配置 -->
<set name="students" table="student_course" inverse="true">
<!-- 当前对象外键列 -->
<key column="course_id"></key>
<many-to-many column="student_id" class="lsq.hibernate.manytomany.Student"></many-to-many>
</set>
</class>
</hibernate-mapping>
案例一、测试保存
多对多关联映射中,不存在一对多那样父子表关系。
在实际开发中,多对多可以不配置 cascade。
* 只要两个对象,建立一次关系,就会向中间表插入一条数据。
student1.getCourses().add(course1); // 产生一条 insert
course1.getStudents().add(student1); // 产生一条 insert
解决: 只需要建立一方面 关联,或者在任何一方 添加inverse=true (推荐)。
package lsq.hibernate.manytomany;
import lsq.hibernate.utils.HibernateUtils;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
//多对多测试
public class HibernateTest {
//测试保存
@Test
public void demo1(){
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
//保存学生
Student student1 = new Student();
student1.setSname("关羽");
Student student2 = new Student();
student2.setSname("张飞");
session.save(student1);
session.save(student2);
//保存课程
Course course1 = new Course();
course1.setCname("语文");
Course course2 = new Course();
course2.setCname("数学");
session.save(course1);
session.save(course2);
//关羽选修语文
student1.getCourses().add(course1);
//course1.getStudents().add(student1);
transaction.commit();
session.close();
}
}
案例二、测试解除关系,删除中间表数据
@Test
public void demo2(){
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Student student = (Student) session.get(Student.class, 1);
Course course = (Course) session.get(Course.class, 1);
//解除关系
student.getCourses().remove(course);
transaction.commit();
session.close();
}
案例三、改变学生选课关系
student.getCourses().remove(course); 删除选课数据
student.getCourses().add(course); 重新选课
案例四、学生存在选课记录,学生数据能否删除
可以,先删除关羽所有选课记录,再删除关羽数据
* 如果删除课程,先删除选课记录,再删除课程
@Test
public void demo3(){
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Student student = (Student) session.get(Student.class, 1);
//删除学生
session.delete(student);
transaction.commit();
session.close();
}
可以,使用 cascade 级联
* 多对多 最好不要使用 级联操作
// 删除课程,将选该课程的学生删除
// 课程---> 学生 配置Course.hbm.xml
// <set name="students" table="student_course" cascade="delete">
@Test
public void demo4() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Course course = (Course) session.get(Course.class, 1);
session.delete(course);
transaction.commit();
session.close();
}