Hibernate中的双向列表映射指的是在两个实体类之间建立一对多/多对一的关联关系,并且双方都能访问对方。这种映射关系在数据库层面通常通过外键实现,在Java对象层面则通过集合和引用实现。
这是最常见的双向列表映射,例如部门(Department)和员工(Employee)的关系。
// Department.java (一方)
@Entity
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "department", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Employee> employees = new ArrayList<>();
// 辅助方法,用于维护双向关系
public void addEmployee(Employee employee) {
employees.add(employee);
employee.setDepartment(this);
}
public void removeEmployee(Employee employee) {
employees.remove(employee);
employee.setDepartment(null);
}
// getters and setters
}
// Employee.java (多方)
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "department_id")
private Department department;
// getters and setters
}
例如学生(Student)和课程(Course)的关系。
// Student.java
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinTable(name = "student_course",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id"))
private List<Course> courses = new ArrayList<>();
// 辅助方法
public void addCourse(Course course) {
courses.add(course);
course.getStudents().add(this);
}
public void removeCourse(Course course) {
courses.remove(course);
course.getStudents().remove(this);
}
// getters and setters
}
// Course.java
@Entity
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToMany(mappedBy = "courses")
private List<Student> students = new ArrayList<>();
// getters and setters
}
当双向关联的对象互相引用时,JSON序列化可能导致无限递归。
解决方案:
@JsonIgnore
或@JsonManagedReference
和@JsonBackReference
注解加载一个实体时可能加载过多关联数据。
解决方案:
FetchType.LAZY
进行懒加载@NamedEntityGraph
定义需要加载的关联属性手动修改一方可能导致另一方不一致。
解决方案:
不恰当的级联可能导致意外删除数据。
解决方案:
cascade
属性orphanRemoval
代替级联删除mappedBy
指定另一方是关系的拥有者FetchType.LAZY
,只在需要时加载关联数据双向列表映射是Hibernate中强大的功能,正确使用可以大大简化数据访问层的代码,但需要注意维护关系的一致性和性能优化。