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;
}
}
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();
}
}