欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-04-24 11:05:41
...

如果要搭建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<Teacher> 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", 
		[email protected](name="teacher_id"),
		[email protected](name="student_id"))//指定关联的中间表
	public Set<Teacher> getTeachers() {
		return teachers;
	}

	public void setTeachers(Set<Teacher> 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<Student> 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<Student> getStudents() {
		return students;
	}

	public void setStudents(Set<Student> 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 多对多