hibernate - 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 表将如下所示(不包括详细信息列):
╔════╦══════════════╦══════╗
║ Id ║ User ║ Age ║
╠════╬══════════════╬══════╣
║ 1 ║ Foo Bar ║ 55 ║
╚════╩══════════════╩══════╝
在此之后我不知道初始值是否为 35。我需要的是下面的审计表:
╔════╦══════════════╦══════════╦═════════╗
║ Id ║ User ║ OldAge ║ New Age ║
╠════╬══════════════╬══════════╬═════════╣
║ 1 ║ Foo Bar ║ 35 ║ 55 ║
╚════╩══════════════╩══════════╩═════════╝
如何使用 Hibernate Envers 实现此类审计?
解决方案
看起来你可能是
- 手动播种数据库并绕过 Hibernate
- 为已有数据的实体映射启用 Hibernate Envers
为了让 Envers 响应更改,通过 Hibernate 完成数据库更改至关重要,以便其事件框架触发所有负责生成审计历史的 Envers 侦听器。如果任何步骤绕过这一点,将不会生成审计条目。
Envers 也不会为已有数据的实体映射生成审计历史。期望是您的实体表是空的,并且插入、更新和删除事件将被 Hibernate 捕获,传播到 Envers,并且审计历史将基于这些变化。对于现有数据,没有事件,因此不会自动生成审计历史记录。如果您打算对具有现有数据的表启用审计,则由实施者正确地播种审计历史记录。
因此,如果我们退后一步,假设您没有在 ORM 基表中已存在数据的实体上手动播种或启用 Envers,那么您的审计表在更新后应该如下所示:
+---+--------------------+-----+-----+---------+
|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 |
+---+--------------------+-----+-----+---------+
您会注意到该列REVTYPE
。此列表示与行突变相关的操作。这些值是枚举类型的一部分,其中:
- 0 = 插入
- 1 = 更新
- 2 = 删除
Envers 查询 API 允许您获取给定实体主键的修订号列表,然后您可以从那里获取每个修订并使用任何差异库执行对象实例之间的差异或编写您自己的。
Envers 还支持一个名为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 |
+---+--------------------+----------+-----+---------+-----+---------+
这些_MOD
列很有用,因为它允许您构建复杂的查询来检查某些感兴趣的列是否在修订中发生了变化。虽然它不允许您从当前审计行中获取先前的值,但可以通过查看该实体主键的审计表历史来推断该信息。
您可能会问,如果 Envers 可以添加这些_MOD
列,为什么不能添加这些“先验值”列。理论上我们可以做到这一点,但我认为退后一步并衡量这是否真的有价值很重要。
我认为以这样一种方式增强查询 API 会更有价值,即用户可以要求 Envers 生成实体历史的某种表示,可能是两个具体修订之间的差异,或者可能是两个修订之间的生命周期。然后,此表示将允许您从中获取先前值和当前值。
简而言之,不需要更改架构,因为 API 会完全为您执行此操作。
推荐阅读
- sql - 如何删除 where 子句语句中的条件检查?
- r - 当其他几个列中的任何一个为 TRUE(或 1)时,使用 mutate() 创建新列
- javascript - 如果我需要根据 javascript 中的条件更新 pin,我的代码可以提高效率吗?
- javascript - 在 React 中使用按钮过滤数组
- java - java是否支持条件语句中的内联声明和赋值?
- python - 为我的 Django 项目激活虚拟环境后,使用“python manage.py runserver”命令时,为什么我的 CMD 提示不执行任何操作
- azure - Azure Dev Ops - Web 应用部署期间的网站建设中页面
- node.js - 如何修复 npm install sqlite3 失败?
- python - 为什么在向字典添加键时会出现 KeyError?
- reactjs - 如何在 firestore .forEach 循环内进行异步调用?