本次实验环境:spring boot + spring data jpa + hibernate
本次实验用例:
学生:
id
name
teachers
教师:
id
nr
students
本次实例展示如何编写多对多双向关系,直接展示常用的编写方式,不再涉及假设讨论。
#Teacher类:
@Entity
@Table(name="t_n2n_teacher")
public class Teacher {
@Id
@GeneratedValue
private Long id;
private String name;
@ManyToMany
@JoinTable(name="t_teacher_student", joinColumns=@JoinColumn(name="teacher_id"), inverseJoinColumns=@JoinColumn(name="student_id"))
private List<Student> students;
//getter与setter省略
}
@JoinTable设置中间表,name为中间表名,joinColumns为本类在中间表中的字段,inverseJoinColumns为另一方在中间表中的字段。
#Student类:
@Entity
@Table(name="t_n2n_student")
public class Student {
@Id
@GeneratedValue
private Long id;
private String name;
@ManyToMany
@JoinTable(name="t_teacher_student", joinColumns=@JoinColumn(name="student_id"), inverseJoinColumns=@JoinColumn(name="teacher_id"))
private List<Teacher> teachers;
//getter与setter省略
}
#生成表
CRUD:
- 添加teacher,直接添加即可。
Teacher teacher = new Teacher();
teacher.setName("李老师");
teacherDao.saveAndFlush(teacher); - 更新teacher,先查出原有数据再更新。
Teacher teacher = teacherDao.findOne(1L);
teacher.setName("李教授");
teacherDao.saveAndFlush(teacher); - 删除teacher,级联删除中间表对应数据。
teacherDao.delete(1L);
查询teacher,@ManyToMany默认为懒加载。
Teacher findOne = teacherDao.findOne(1L);
System.err.println(findOne.getName());添加student,直接添加。
Student student = new Student();
student.setName("小红");
studentDao.saveAndFlush(student);- 更新student,先查出原有数据再更新。
Student student = studentDao.findOne(1L);
student.setName("大明");
studentDao.saveAndFlush(student); - 删除student,级联删除中间表对应数据。
studentDao.delete(1L);;
查询student,@ManyToMany默认烂加载。
Student findOne = studentDao.findOne(1L);
System.err.println(findOne.getName());添加student和teacher关系,不管从student方还是teacher方都能设置,但是得保证在同一个session中
@Transactional
public void teach() {
Teacher teacher = teacherDao.findOne(1L);
Student student = studentDao.findOne(1L);
List<Student> students = teacher.getStudents();
students.add(student);
teacherDao.saveAndFlush(teacher);
}
@Transactional
public void learn() {
Student student = studentDao.findOne(1L);
Teacher teacher = teacherDao.findOne(1L);
List<Teacher> teachers = student.getTeachers();
teachers.add(teacher);
studentDao.saveAndFlush(student);
}
- 删除关系,即删除中间表的数据,建议直接通过原生的sql实现。
@Modifying
@Transactional
@Query(nativeQuery=true, value="delete from t_teacher_student where teacher_id=?1 and student_id=?2")
public int notTeach(Long teacherId, Long studentId);
@Modifying
@Transactional
@Query(nativeQuery=true, value="delete from t_teacher_student where teacher_id=?1 and student_id=?2")
public int notLearn(Long teacherId, Long studentId);
notTeach方法定义在TeacherDao中,notLearn方法定义在StudentDao中,不管通过哪一方都能删除。