在JPA中跟踪属性的变化

16

目前,我正在处理一个具有持久性管理方面的一些非常规要求的 Java EE 项目。用户对实体所做的更改首先需要应用到某个工作副本中,然后再进行验证,之后才会应用到“实时数据”上。在那个实时数据上做出的任何更改也需要有一些记录,以便进行审计。

这些实体是通过 JPA 管理的,而 Hibernate 将用作提供程序。这是一个给定的条件,因此我们不会回避与 Hibernate 相关的内容。对于第一个要求,使用了两个持久性单元。其中一个将实体映射到“实时数据”表,另一个将实体映射到“工作副本”表。对于第二个要求,我们将使用 Hibernate Envers,它非常适合我们的用例。

目前为止都很顺利。现在,当用户在(基于 Web 的)前端查看数据时,能够指示哪些字段在工作副本中与实时数据相比已更改将非常有用。使用不同的颜色就足够了。为此,我们需要一种方法来确定哪些属性已被更改。我的问题是,有什么好方法可以解决这个问题?

使用 JavaBeans API,PropertyChangeListener 可以足够地通知任何工作副本实体中的更改并保留它们的集合。但是,该集合还需要被持久化,因为应用程序可能会重新启动,并且更改在验证和应用于实时数据之前可能具有长期性质。每次需要它时将实时数据应用于工作副本以获取更改是不可行的(因此使用了两个持久性单元)。 我们也可以比较工作副本与实时数据并查找不同的字段。一些内省和反射代码就足够了,但是这似乎非常耗费处理能力,更不用说需要获取实时数据了。 也许我错过了某些简单的东西,或者有人知道我可以使用的一个出色的 JPA/Hibernate 功能。即使我无法避免(a)单独的数据库表存储此类信息,但对于这种情况的最佳实践或实际经验可能非常有用。

我知道这是一个半开放性的问题,但其他人肯定也遇到过类似的要求。欢迎提供任何好的建议,如果有现成解决方案的指针则更佳,可以作为被接受的答案。


你有试过使用 Hibernate Envers 吗? - Xavier Dury
@XavierDury 在帖子中明确提到我们使用Envers来保留更改历史记录。我正在寻找的是一种实时的方式,以了解特定实体中更改了哪些属性,这样我们就可以向用户展示它,而无需每次显示它们时都比较两个版本的实体所带来的巨大开销。 - G_H
1
@G_H 只是想知道:加载两个版本的相同实体进行比较真的很糟糕吗?我的意思是,这些实体有什么“特别”的地方吗?如果您始终保持持久层尽可能精简,我不认为这会成为性能问题。 - Bonifacio
2
啊,完全忽略了“工作副本也是持久化的”这部分。现在更清楚了。不用考虑实体监听器之类的,这是不同的。你基本上需要一个“JavaBean差异”,确实存在相关库(尝试在搜索中使用该关键字)。虽然我从未尝试过,所以无法从经验上发言。 - BalusC
1
这对我来说有点像一个CQRSEventStore的应用程序。 - Steve C
显示剩余6条评论
1个回答

0
也许你可以使用Hibernate刷新实体事件监听器。在刷新之前,脏属性会被计算出来。你可以将它们存储在数据库中的某个地方。
这里有一个示例代码,演示了如何使用Hibernate的脏属性特性,或许能给你一些启发。

最终我们并没有真正需要这个(尚未),只是向用户呈现“工作副本”。如果在某个时刻需要明确标记所更改的内容,则刷新侦听器可能是最佳方法,因此我将其标记为已接受。我认为类org.hibernate.EmptyListener可以提供查找脏属性的基础。您的链接已经404了,因此最好用一些SO问题/答案替换它,以提供有关如何自定义脏属性处理的信息。 - G_H

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接