【问题标题】:Updating multiple versions of JPA entity更新多个版本的 JPA 实体
【发布时间】:2015-05-27 09:43:53
【问题描述】:
背景-> 我有一个员工表,它由代码中的许多 JPA 实体表示 - EmployeeBasic 和 EmployeeDetails。
这些 JPA 实体中的每一个都有不同级别的详细信息 - 基本实体只有员工姓名和 ID。详细实体除了名称和 ID 外,还有其他详细信息,例如开始日期、部门等。
现在来解决问题 -> 我在代码中有一个位置,它使用 EmployeeBasic 实体更新实体的名称。在代码的另一部分,正在使用 EmployeeDetails 实体。但是,它不会自动与更新的名称同步。有没有办法在 JPA 中处理它,以便实体的两个版本同步?
【问题讨论】:
标签:
hibernate
jpa
ejb
eclipselink
【解决方案1】:
不,JPA/Hibernate 中没有这种行为。
自动同步是不可能的,因为 Hibernate 直到刷新时间才知道对象修改。所以当你更改EmployeeBasic 的名字时,Hibernate 在脏检查之前不会注意到它。
但是,我认为无论如何制作这样的东西都不是一个好的设计。最好的方法是将映射到同一个表(行)的所有不同实体统一到一个实体中,这样持久化上下文就永远不会处于与 DB 和其他实体相关的不一致状态。
【解决方案2】:
JPA 允许在不同层进行缓存,因此即使所有进程都使用同一个 Employee 实体,也需要仔细设计以确保所有进程都自动与更新后的名称同步。这样做的原因是 EntityManager 是要被事务处理的;从中读取将为您提供实体的托管实例,然后将其与其他 EntityManager 中所做的更改隔离开来。数据库中的数据只有在写入时才需要考虑。这使您可以处理它们而不必担心数据会从您下面改变,并自己管理任何问题(建议使用某种形式的乐观锁定)。
您的情况也很复杂,因为尽管 EmployeeBasic 和 EmployeeDetails 可以重用同一个数据库表,但 JPA 也允许共享缓存。因此,对 EmployeeBasic 进行更改将更新其缓存和共享缓存,但 EmployeeDetails 缓存将是陈旧的。这类似于让多个持久性单元访问同一个表。
处理这种情况的方式是应用程序负责并且可以控制何时刷新其实体、缓存级别和缓存失效。 JPA 允许关闭共享缓存(使用隔离缓存),这样当您从新的 EntityManager 读取数据时,它总是会去数据库获取数据,并查看任何实体中的更改。它还具有刷新 api(并且大多数提供程序都有刷新提示),允许您在知道可能需要检查某些内容时强制查询数据库,但必须小心,因为它会消除更改。
EclipseLink(我不熟悉 Hibernate)具有缓存失效选项和缓存协调,可以与事件一起使用,以便您可以利用共享缓存;您可以使用更新事件来触发与该更新相关的所有 Employee** 缓存失效。