维护端注解
@ManyToMany(cascade = CascadeType.REFRESH)
@JoinTable(//关联表
name = "student_teacher", //关联表名
inverseJoinColumns = @JoinColumn(name = "teacher_id"),//被维护端外键
joinColumns = @JoinColumn(name = "student_id"))//维护端外键
被维护端注解
@ManyToMany(
cascade = CascadeType.REFRESH,
mappedBy = "teachers",//通过维护端的属性关联
fetch = FetchType.LAZY)
关系维护端删除时,如果中间表存在些纪录的关联信息,则会删除该关联信息;
关系被维护端删除时,如果中间表存在些纪录的关联信息,则会删除失败.
以学生和老师的对应关系为例。一个学生可以拥有多个老师,一个老师也可以拥有多个学生。
学生实体类
- package com.taoistwar.jpa.entity.manytomany;
- 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.GenerationType;
- 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<Teacher>();
- @Id
- @GeneratedValue(strategy = GenerationType.AUTO)
- public Integer getId() {
- return id;
- }
- public void setId(Integer id) {
- this.id = id;
- }
- @Column(nullable = false, length = 16)
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- @ManyToMany(cascade = CascadeType.REFRESH)
- @JoinTable(name = "student_teacher", inverseJoinColumns = @JoinColumn(name = "teacher_id"), joinColumns = @JoinColumn(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 removeTeachers(Teacher teacher) {
- this.teachers.remove(teacher);
- }
- }
重点在于:
- @ManyToMany(cascade = CascadeType.REFRESH)
- @JoinTable(name = "student_teacher", inverseJoinColumns = @JoinColumn(name = "teacher_id"), joinColumns = @JoinColumn(name = "student_id"))
- public Set<Teacher> getTeachers() {
- return teachers;
- }
老师实体类
- package com.taoistwar.jpa.entity.manytomany;
- import java.util.HashSet;
- import java.util.Set;
- import javax.persistence.CascadeType;
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.FetchType;
- import javax.persistence.GeneratedValue;
- import javax.persistence.GenerationType;
- import javax.persistence.Id;
- import javax.persistence.ManyToMany;
- @Entity
- public class Teacher {
- private Integer id;
- private String name;
- private Set<Student> students = new HashSet<Student>();
- @Id
- @GeneratedValue(strategy = GenerationType.AUTO)
- public Integer getId() {
- return id;
- }
- public void setId(Integer id) {
- this.id = id;
- }
- @Column(nullable = false, length = 16)
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- @ManyToMany(cascade = CascadeType.REFRESH, mappedBy = "teachers", fetch = FetchType.LAZY)
- public Set<Student> getStudents() {
- return students;
- }
- public void setStudents(Set<Student> students) {
- this.students = students;
- }
- @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;
- Teacher other = (Teacher) obj;
- if (id == null) {
- if (other.id != null)
- return false;
- } else if (!id.equals(other.id))
- return false;
- return true;
- }
- }
重点在于:
- @ManyToMany(cascade = CascadeType.REFRESH, mappedBy = "teachers", fetch = FetchType.LAZY)
- public Set<Student> getStudents() {
- return students;
- }
拥有mappedBy注解的实体类为关系被维护端,另外的实体类为关系维护端的。顾名思意,关系的维护端对关系(在多对多为中间关联表)的CRUD做操作。关系的被维护端没有该操作,不能维护关系。
测试类
- package com.taoistwar.jpa.entity.manytomany;
- import javax.persistence.EntityManager;
- import javax.persistence.EntityManagerFactory;
- import javax.persistence.Persistence;
- import org.junit.Test;
- public class ManyToMany {
- @Test
- public void save() {
- EntityManagerFactory emf = Persistence
- .createEntityManagerFactory("JPAPU");
- EntityManager em = emf.createEntityManager();
- em.getTransaction().begin();
- Student student = new Student();
- student.setName("小李");
- Teacher teacher = new Teacher();
- teacher.setName("大李");
- em.persist(student);
- em.persist(teacher);
- em.getTransaction().commit();
- emf.close();
- }
- @Test
- public void bind() {
- EntityManagerFactory emf = Persistence
- .createEntityManagerFactory("JPAPU");
- EntityManager em = emf.createEntityManager();
- em.getTransaction().begin();
- Student student = em.find(Student.class, 1);
- Teacher teacher = em.find(Teacher.class, 1);
- student.addTeacher(teacher);
- em.persist(student);
- em.getTransaction().commit();
- emf.close();
- }
- @Test
- public void unbind() {
- EntityManagerFactory emf = Persistence
- .createEntityManagerFactory("JPAPU");
- EntityManager em = emf.createEntityManager();
- em.getTransaction().begin();
- Student student = em.find(Student.class, 1);
- Teacher teacher = em.find(Teacher.class, 1);
- student.removeTeachers(teacher);
- em.persist(student);
- em.getTransaction().commit();
- emf.close();
- }
- @Test
- public void removeTeacher() {
- EntityManagerFactory emf = Persistence
- .createEntityManagerFactory("JPAPU");
- EntityManager em = emf.createEntityManager();
- em.getTransaction().begin();
- // 关系被维护端删除时,如果中间表存在些纪录的关联信息,则会删除失败
- em.remove(em.getReference(Teacher.class, 1));
- em.getTransaction().commit();
- emf.close();
- }
- @Test
- public void removeStudent() {
- EntityManagerFactory emf = Persistence
- .createEntityManagerFactory("JPAPU");
- EntityManager em = emf.createEntityManager();
- em.getTransaction().begin();
- // 关系维护端删除时,如果中间表存在些纪录的关联信息,则会删除该关联信息
- em.remove(em.getReference(Student.class, 1));
- em.getTransaction().commit();
- emf.close();
- }
- }