JPA之JPA中的多对多双向关联

如果要搭建JPA开发环境,请从JPA第一篇博客看起。


下面的例子以老师和学生的例子进行多对多关系的编码讲解。


1、Student.java中的代码

package cn.sunft.bean;

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

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;

/**
 * 学生
 */
@Entity
public class Student {
	private Integer id;
	private String name;
	private Set teachers = new HashSet<>();

	public Student() {
		super();
	}

	public Student(String name) {
		super();
		this.name = name;
	}

	@Id
	@GeneratedValue
	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	@Column(length = 10, nullable = false)
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	//维护关系的一方
	@ManyToMany(cascade=CascadeType.REFRESH)
	//如果中间表不写inverseJoinColumns和joinColumns属性,
	//Hibernate会自动生成对应的中间表的外键
	@JoinTable(name="student_teacher", 
		inverseJoinColumns=@JoinColumn(name="teacher_id"),
		joinColumns=@JoinColumn(name="student_id"))//指定关联的中间表
	public Set getTeachers() {
		return teachers;
	}

	public void setTeachers(Set teachers) {
		this.teachers = teachers;
	}
	
	public void addTeacher(Teacher teacher){
		this.teachers.add(teacher);
	}

	public void removeTeacher(Teacher teacher){
		if(this.teachers.contains(teacher)){
			this.teachers.remove(teacher);
		}
	}

	//重写hashCode方法,用于判断两个对象是否相等
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}

}

2、Teacher.java中的代码

package cn.sunft.bean;

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

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;

/**
 * 老师
 */
@Entity
public class Teacher {
	private Integer id;
	private String name;
	private Set students = new HashSet<>();

	public Teacher() {
		super();
	}

	public Teacher(String name) {
		super();
		this.name = name;
	}

	@Id
	@GeneratedValue
	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	@Column(length = 10, nullable = false)
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	//多对多关系中,级联删除基本用不上,这里默认是懒加载
	//被维护关系的一方
	@ManyToMany(cascade=CascadeType.REFRESH, mappedBy="teachers")
	public Set getStudents() {
		return students;
	}

	public void setStudents(Set students) {
		this.students = students;
	}

}


3、测试类中的代码

package junit.test;

import javax.persistence.CascadeType;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import org.junit.Test;

import cn.sunft.bean.Student;
import cn.sunft.bean.Teacher;

/**
 * 多对多的测试
 */
public class ManyToManyTest {
	
	/**
	 * 保存学生和老师
	 */
	@Test
	public void save(){
		EntityManagerFactory factory 
			= Persistence.createEntityManagerFactory("sunft_first");
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();
		em.persist(new Student("小张"));
		em.persist(new Teacher("李勇老师"));
		em.getTransaction().commit();
		em.close();
		factory.close();
	}
	
	/**
	 * 建立老师和学生的关系
	 */
	@Test
	public void buildTS(){
		EntityManagerFactory factory 
			= Persistence.createEntityManagerFactory("sunft_first");
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();
		//这里的配置是学生负责维护关系
		Student student = em.find(Student.class, 31);
		//这里并不需要把老师及时加载进来,体现在中间表中添加一条数据
		student.addTeacher(em.getReference(Teacher.class, 32));
		em.getTransaction().commit();
		em.close();
		factory.close();
	}
	
	/**
	 * 解除老师和学生的关系
	 */
	@Test
	public void deleteTS(){
		EntityManagerFactory factory 
			= Persistence.createEntityManagerFactory("sunft_first");
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();
		//这里配置的是学生负责维护关系
		Student student = em.find(Student.class, 25);
		//这里并不需要把老师及时加载进来,使用getReference增加性能,
		//体现在将中间表中的记录删除一条
		student.removeTeacher(em.getReference(Teacher.class, 26));
		em.getTransaction().commit();
		em.close();
		factory.close();
	}
	
	/**
	 * 删除老师:只能先解除和学生的关系,再删除老师,
	 * 老师是关系被维护端,没有权利级联删除关系
	 */
	@Test
	public void deleteTeacher(){
		EntityManagerFactory factory 
			= Persistence.createEntityManagerFactory("sunft_first");
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();
		Student student = em.find(Student.class, 25);
		Teacher teacher = em.getReference(Teacher.class, 26);
		//这里并不需要把老师及时加载进来,体现在将中间表中的记录删除一条
		student.removeTeacher(teacher);//解除关系
		em.remove(em.getReference(Teacher.class, 26));//删除老师
		em.getTransaction().commit();
		em.close();
		factory.close();
	}
	
	/**
	 * 删除学生:因为由学生维护关系,因此删除学生会删除关系,
	 * 但是只有当cascade=CascadeType.REMOVE时,才会连着
	 * 学生一起删除
	 */
	@Test
	public void deleteStudent(){
		EntityManagerFactory factory 
			= Persistence.createEntityManagerFactory("sunft_first");
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();
		Student student = em.getReference(Student.class, 31);
		//这里会删除关系
		em.remove(student);//删除老师
		em.getTransaction().commit();
		em.close();
		factory.close();
	}
}



你可能感兴趣的:(JPA,多对多)