休眠带来新旧价值

时间:2019-10-18 11:12:34

标签: hibernate jpa spring-data-jpa hibernate-envers

我有一个如下表。

╔════╦══════════════╦══════╗
║ Id ║     User     ║ Age  ║
╠════╬══════════════╬══════╣
║  1 ║ Foo Bar      ║  35  ║
║  2 ║ Bar Foo      ║  40  ║
║  3 ║ Bob Dixon    ║  50  ║
║  4 ║ Alice Spolsky║  59  ║
╚════╩══════════════╩══════╝

现在这些是初始值,我想使用Hibernate Envers存储审核,包括所有旧值和新值。默认配置仅允许我存储新值,因此错过了第一个创建的对象的值。例如,如果我说将第一个年龄更新为55岁,那么aud表将如下所示(不包括detail列):

╔════╦══════════════╦══════╗
║ Id ║     User     ║ Age  ║
╠════╬══════════════╬══════╣
║  1 ║ Foo Bar      ║  55  ║
╚════╩══════════════╩══════╝

在这之后,我不知道初始值是否为35。我需要的是下面的审核表:

╔════╦══════════════╦══════════╦═════════╗
║ Id ║     User     ║ OldAge   ║ New Age ║
╠════╬══════════════╬══════════╬═════════╣
║  1 ║ Foo Bar      ║  35      ║   55    ║
╚════╩══════════════╩══════════╩═════════╝

如何使用Hibernate Envers实现此类审核?

1 个答案:

答案 0 :(得分:1)

看来您也许是

  1. 手动播种数据库并绕过Hibernate
  2. 为已具有数据的实体映射启用Hibernate Envers

为了使Envers能够响应更改,至关重要的是必须通过Hibernate完成数据库更改,以便其事件框架可以触发负责生成审核历史记录的所有Envers侦听器。如果有任何步骤绕过此步骤,则不会生成审核条目。

Envers也不为已具有数据的实体映射生成审核历史记录。期望您的实体表为空,并且Hibernate将捕获插入,更新和删除事件,并将其传播到Envers,并且审计历史将基于这些事件进行更改。对于现有数据,没有事件,因此不会自动生成审核历史记录。如果您打算对具有现有数据的表启用审核,则由实施者正确 seed 审核历史记录。

因此,如果我们退后一步,假设您没有手动对具有ORM基本表中已经存在的数据的实体进行播种或启用Envers,则您的审核表应如下所示:您的更新:

.git

您会注意到+---+--------------------+-----+-----+---------+ |Id | User | Age | REV | REVTYPE | +---+--------------------+-----+-----+---------+ | 1 | Foo Bar | 35 | 1 | 0 | | 2 | Bar Foo | 40 | 1 | 0 | | 3 | Bob Dixon | 50 | 1 | 0 | | 4 | Alice Spolsky | 59 | 1 | 0 | | 1 | Foo Bar | 55 | 2 | 1 | +---+--------------------+-----+-----+---------+ 列。该列表示与行突变相关的操作。这些值是枚举类型的一部分,其中:

  • 0 =插入
  • 1 =更新
  • 2 =删除

通过Envers Query API,您可以获取给定实体主键的修订号列表,然后可以从其中获取每个修订,并使用任何diff库或编写自己的差异库来执行对象实例之间的区别。

Envers还支持称为REVTYPE的注释属性。默认情况下,此功能是禁用的,因为它会向实体模型添加大量其他支持列,但是启用后,您的模型实际上将如下所示:

withModifiedFlags

这些+---+--------------------+----------+-----+---------+-----+---------+ |Id | User | User_MOD | Age | Age_MOD | REV | REVTYPE | +---+--------------------+----------+-----+---------+-----+---------+ | 1 | Foo Bar | 1 | 35 | 1 | 1 | 0 | | 2 | Bar Foo | 1 | 40 | 1 | 1 | 0 | | 3 | Bob Dixon | 1 | 50 | 1 | 1 | 0 | | 4 | Alice Spolsky | 1 | 59 | 1 | 1 | 0 | | 1 | Foo Bar | 0 | 55 | 1 | 2 | 1 | +---+--------------------+----------+-----+---------+-----+---------+ 列很有用,因为它使您可以构建复杂的查询来检查某些感兴趣的列在修订中是否发生了变化。虽然它不允许您从当前审核行中获取先前的值,但可以通过查看该实体主键的审核表的历史来推导该信息。

您可能会问,Envers是否可以添加这些_MOD列,为什么不添加这些“优先级”列。从理论上讲,我们可以做到这一点,但是我认为退一步并衡量它是否真的很重要很重要。

我认为,以用户可以要求Envers生成实体历史的某种表示形式(可能是两个具体修订版之间的差异,或者可能是两个修订版之间的整个生命周期)的方式来增强Query API会更有价值。然后,该表示形式将使您能够从中获取先前值和当前值。

简而言之,由于API将完全为您完成此操作,因此无需更改架构。