作为一项新要求,我必须将记录校验和保存在数据库中。
我们有一个单独的校验和表,其中包含table_name,record_id,record_version,checksum和其他一些字段。
我们还有一个基础实体类,它使用@PostPersist
,@PostUpdate
和@PostLoad
方法保存和读取校验和数据。
让我们假设以下基本示例:
我们有一个Teacher
,Course
和一个TeacherCourse
实体。 Teacher
实体具有addCourse
方法:
public void addCourse(Long courseId) {
JpaTeacherCourse tc = new JpaTeacherCourse();
JpaCourse course = new JpaCourse();
course.setId(courseId);
tc.setCourse(course);
tc.setTeacher(this);
tc.setStartDate(new Date());
courses.add(tc);
}
在BaseEntity
方法的@PostLoad
中,我们使用查询加载最新的校验和数据:
@Query(value = "SELECT * FROM checksums c WHERE c.table_name = :tableName AND c.record_id = :recordId ORDER BY id DESC LIMIT 1", nativeQuery = true)
问题在于,在保存Teacher
实体的过程中,Hibernate加载了适当的过程,并触发了@PostLoad
方法。 @PostLoad
中的选择触发Hibernate刷新数据,最终结果是Flush during cascade is dangerous
异常。
我想这是因为Hibernate没有引用课程实体。如果我将addCourse
方法修改为此:
public void addCourse(Long courseId) {
JpaTeacherCourse tc = new JpaTeacherCourse();
CourseRepository repo = BeanUtil.getBean(CourseRepository.class);
Optional<JpaCourse> courseOpt = repo.findById(courseId);
JpaCourse course = courseOpt.get();
tc.setCourse(course);
tc.setTeacher(this);
tc.setStartDate(new Date());
courses.add(tc);
}
在这种情况下,在save方法期间不会触发选择,并且保存实体可以正常工作。
此解决方案的我的问题是,实体依赖于存储库,而这似乎不是最佳解决方案。
如果addCourse
方法将实体作为参数,则可能是另一种选择,但是它需要在其他地方进行大量代码更改,并且还可以添加没有真正的Hibernate引用作为参数的实体,这就是再次是原始问题。
所以我的问题是如何正确解决此问题?
该项目基于Spring Boot 2.1并使用Hibernate 5.3