Hibernate关联关系映射之多对多关联关系

本次仍然使用一个示例的方式进行演示,学生与教师之间的关系就是一个典型的多对多关系,一个教师可以有多个学生,同样一个学生也可以有多个教师。在数据库中存储需要一张学生表存储学生信息,一个教师表存储教师信息,为了表示他们之间的关系我们需要一个中间表来表示他们之间的联系。

例如,在教师表中有id,name两个属性,学生表中同样有id,name两个属性。教师表中有两条记录分别是(1,董老师),(2,李老师);学生表中同样有两条(1,张三),(2,李四)。在中间表中有两个字段(teacherId,studentId),这两个字段构成一个联合主键,同时这两个字段又是教师表和学生表的外键,老师和学生进行关联的时候直接插入关联的老师和学生的id在中间表内即可,例如在中间表中插入(1,1)表示董老师与张三进行关联,插入(1,2)表示董老师与李四关联。

下面我们看一下Teacher类和Student类

package entity;

import java.util.HashSet;
import java.util.Set;

public class Teacher {
	private Long id;
	private String name;
	private Set<Student> students = new HashSet<Student>();
	public Long getId() {
		return id;
	}
	public void setId(Long 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;
	}
}
package entity;

import java.util.HashSet;
import java.util.Set;

public class Student {
	private Long id;
	private String name;	
	private Set<Teacher> teachers = new HashSet<Teacher>();
	
	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Set<Teacher> getTeachers() {
		return teachers;
	}
	public void setTeachers(Set<Teacher> teachers) {
		this.teachers = teachers;
	}	
}

在POJO类中仍然使用集合表示有多条记录。

下面在看一个他们的映射配置文件

首先看Teacher.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="entity.Teacher" table="Teacher" schema="MYHR">
        <id name="id" type="long">
            <column name="ID"/>
            <generator class="assigned" />
        </id>
        <property name="name" type="string">
            <column name="NAME" not-null="true" />
        </property>
        <!-- students属性,Set集合,表示本类与Student类的多对多关系 -->
        <set name="students" table="teacher_student" inverse="false">
            <key column="teacherId" />
            <many-to-many class="entity.Student" column="studentId"/>
        </set>
    </class>
</hibernate-mapping>

类中的Set类型的属性在映射配置文件中仍然使用<set>标签进行映射,在<set>标签中使用<many-to-many>表示他们之间的关系是多对多。

然后看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="entity.Student" table="Student" schema="MYHR">
        <id name="id" type="long">
            <column name="ID" />
            <generator class="assigned" />
        </id>
        <property name="name" type="string">
            <column name="NAME" not-null="true" />
        </property>
        <!-- teachers属性, Set集合,表示本类与Teacher类的多对多关联关系-->
        <!-- table:是实现多对多映射的中间表 -->
        <!-- key:集合外键(引用当前表主键的那个外键) -->
        <set name="teachers" table="teacher_student">
            <key column="studentId" />
            <many-to-many class="entity.Teacher" column="teacherId"/>
        </set>
    </class>
</hibernate-mapping>

这样,教师和学生之间的多对多关联映射就配置完了,下面看一下测试类。这里使用JUtil进行测试

package test;

import static org.junit.Assert.*;

import java.util.Iterator;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.Transaction;

import entity.Student;
import entity.Teacher;
import factory.HibernateSessionFactory;

public class Test {

	private Session session = null;
	private Transaction tran = null;

	// 存储对象
	@org.junit.Test
	public void save() {
		session = HibernateSessionFactory.getSession();
		tran = session.beginTransaction();
		try {
			Teacher teacher = new Teacher();
			teacher.setId(1L);
			teacher.setName("董老师");

			Teacher t2 = new Teacher();
			t2.setId(2l);
			t2.setName("李老师");

			Student s1 = new Student();
			s1.setId(1L);
			s1.setName("李四");

			Student s2 = new Student();
			s2.setId(2l);
			s2.setName("张三");

			teacher.getStudents().add(s1);
			teacher.getStudents().add(s2);
			t2.getStudents().add(s1);
			t2.getStudents().add(s2);
			s1.getTeachers().add(teacher);
			s1.getTeachers().add(t2);
			s2.getTeachers().add(teacher);
			s2.getTeachers().add(t2);

			session.save(teacher);
			session.save(t2);
			session.save(s1);
			session.save(s2);

			tran.commit();
		} catch (Exception e) {
			tran.rollback();
		}
	}

	// 获取老师信息
	@org.junit.Test
	public void GetTeacher() {
		session = HibernateSessionFactory.getSession();
		tran = session.beginTransaction();
		try {
			Teacher teacher = (Teacher) session.get(Teacher.class, 1l);
			Set<Student> set = teacher.getStudents();
			System.out.println(teacher.getName() + "的学生是:");
			Iterator<Student> it = set.iterator();
			while (it.hasNext()) {
				Student s = it.next();
				System.out.println(s.getName());
			}
			tran.commit();
		} catch (Exception e) {
			tran.rollback();
		}
	}

	// 解除关联关系
	@org.junit.Test
	public void RemoveRelation() {
		session = HibernateSessionFactory.getSession();
		tran = session.beginTransaction();
		try {
			Student s = (Student) session.get(Student.class, 1l);
			Teacher teacher = (Teacher) session.get(Teacher.class, 1l);
			// 如果Teacher的inverse属性为false可以解除,如果为true不可以解除
			teacher.getStudents().remove(s);
			tran.commit();
		} catch (Exception e) {
			tran.rollback();
		}
	}

	// 删除关联关系
	@org.junit.Test
	public void DeleteRelation() {
		session = HibernateSessionFactory.getSession();
		tran = session.beginTransaction();
		try {
			Teacher teacher = (Teacher) session.get(Teacher.class, 2l);
			// 当teacher的inverse属性为false时,可以将教师信息删除,并且将中间表中相关记录删除
			// 当inverse属性为true时将教师信息删除时抛出异常
			session.delete(teacher);
			tran.commit();
		} catch (Exception e) {
			tran.rollback();
		}
	}
}


 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。