【发布时间】:2017-01-24 13:07:42
【问题描述】:
我正在做一个项目,我们在数据库中有两个实体副本,具有不同的表(它使用两个具有相同类的持久性单元,但其中一个具有不同表名的映射文件)。有工作副本和实时数据。对工作副本的更改可以应用于实时数据,但也可以撤消。在工作副本中创建的任何实体都必须删除,任何更新的实体必须再次与实时数据保持一致。
编辑可以指定是否更新其直接目标。如果它只更新实体层次结构中的后代,或者创建一些新的后代,则“目标”实体不会直接更改,也不必再次与实时数据同步。这很重要,因为撤消编辑可能会导致其他编辑也被撤消/删除,如果它们碰巧影响相同的实体。我想尽可能减少这种“副作用”。
假设我们有一个Course 类,它可以有任意数量的Students。我希望关系是双向的。该课程有一组学生,并在@OneToMany 注释中指定“mappedBy”。
@Entity
public class Course {
// Primary key and other fields would be here...
@OneToMany(mappedBy = "course", fetch = FetchType.LAZY)
private List<Student> students;
// Getters, setters...
}
从数据库的角度来看,学生类是拥有方(它将具有 Course 表的外键)并指定 @JoinColumn。
@Entity
public class Student {
// Primary key and other fields...
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "course_id")
private Course course;
// Getters and setters...
}
没有级联操作。不是 MERGE、PERSIST、REMOVE... 或任何东西。由于整个事情的运作方式,这些事情都是由编辑框架处理的。整个事情在 Java EE 中运行,事务由容器处理。
编辑可能会创建一个新学生并将其添加到课程中。比如:
Course course;
// Fetch the course from persistence
Student student = new Student("John Doe");
student.setCourse(course);
course.getStudents().add(student);
为了保持数据模型一致,为学生设置了课程,在课程中也将学生添加到列表中。 course_id 列在持久化学生时正确填写。
如果修改未应用于实时数据但已撤消,则必须删除已创建的学生实体。那么出现的问题是如何看待课程。从某种意义上说,它被更新了,因为它的收藏中添加了一些东西。但是,不必对课程的数据库进行任何更改。它不是 RDBMS 中关系的拥有方。如果我们从实时数据中同步了课程,则可能需要撤消或删除对课程的其他更改。如果我们不这样做,他们可能会留下来。
假设我在一个 JTA 事务中并且注入了一个实体管理器。如果我从中获取学生并对其执行删除操作,我认为我不需要显式获取课程并将学生从集合中删除。
问题:
- 如果我已经获取了课程怎么办?
- 可以将学生留在集合中吗?
- 当它尝试在事务结束时合并课程时是否会抛出异常,因为它是一个托管实体?
假设事务中唯一会发生的事情以及其中的持久性上下文是删除/同步这些实体,因此在 Java 端的集合会在短时间内不一致并不是真正的问题。如果它包含必须删除的实体,框架代码将考虑它,并且对象的保留时间不会超过事务。
【问题讨论】:
标签: java jpa jakarta-ee bidirectional consistency