为了账号安全,请及时绑定邮箱和手机立即绑定

字段更改的休眠审计日志

字段更改的休眠审计日志

米琪卡哇伊 2022-06-04 14:58:50
如何将实体的更改记录到日志文件中?考虑我有Person这样的。import org.hibernate.envers.Audited;import javax.persistence.Entity;import javax.persistence.Id;import javax.persistence.GeneratedValue;import javax.persistence.Column;@Entity@Auditedpublic class Person {    @Id    @GeneratedValue    private int id;    private String name;    private String surname;// add getters, setters, constructors, equals and hashCode here}和改变现有的代码PersonPerson p1 = new Person("name-1", "surname-1");personRepository.save(p1);Person p2 = personRepository.findOne(1L);p2.setName("new-name");personRepository.save(p2);我怎么能有旧实体新实体字段列表已更改(类似于Diffable的结果)在我的日志文件中?我知道envars可以将更改存储在 db 中并让我稍后提取它们,AuditReader但我喜欢将更改存储在 Json 文件中以将它们发送到第三方应用程序(如 Elastic)。
查看完整描述

2 回答

?
回首忆惘然

TA贡献1847条经验 获得超11个赞

我实际上会从两个角度来解决这个问题。


使用 Envers 获得的好处之一是您可以非常快速地注释您的实体并准确告诉框架您希望如何跟踪实体模型的更改。更好的是,您可以让 Envers 自动为您生成 diffable 字段。


让我们来看看这个基本实体:


@Entity

@Audited(withModifiedFlag = true)

public class Person {

  @Id

  @GeneratedValue

  private Integer id;

  private String name;

}

当您启用该withModifiedFlag功能时,这会通知 Envers 将一些额外的元数据列添加到该实体的审计表中,因此该实体的审计表基本上如下所示:


+----+------+----------+-----+---------+

| ID | name | name_MOD | REV | REVTYPE |

+----+------+----------+-----+---------+

这样做的好处是,如果您使用某些流程直接从表中导出和流式传输数据,您不再需要实际区分当前行与前一行来了解发生了什么变化;只需查看关联的_MOD列是1(true) 还是0(false),模式就会自动告诉您这一点。


从这一点开始,您有几个选择。


本机查询 ETL

您可以使用 Hibernate 本机查询通过某个后台应用程序线程或单独的后台进程来提取数据并将其转换为 ES 的 JSON。由于该_MOD列为您提供了字段更改的指示符,因此您可以轻松读取行并构建必要的数据,而无需在提取时执行差异操作。


我还建议配置 Envers 以将审计对象放在单独的目录/模式中。这最大限度地提高了数据库同时改进跨多个数据库的磁盘 IO 的能力。


Debezium ETL

Debezium 项目是处理数据复制的绝佳方式。它的强大优势之一是它使用户能够跨完全适合您的模型的异构平台执行此操作。


这里最大的区别是 Debezium 不直接读取数据库来确定更改,而是读取数据库事务日志文件并生成一系列事件来描述针对该数据库发生的 DML 操作。简而言之,您避免了您非常关心的读取操作,因为 Debezium 直接从事务日志中重新水化状态。

举个例子:

  1. 休眠执行INSERT INTO Person (?,?) VALUES (?,?)

  2. Hibernate Envers 执行INSERT INTO Person_AUD (...) VALUES (....)

  3. 数据库将该操作写入重做/事务日志。

  4. Debezium 注意到日志已写入,然后读取条目。

  5. Debezium 为Person_AUD(订阅的表)生成一个插入事件。

  6. 该事件的任何注册相关方都会收到并处理它。

在 (5) 中,您的转换/加载代码将存在以接收该插入事件并生成 JSON 输出并将其发送到 ES。

包起来

通过使用 Debezium,您能够以极其高效的方式有效地离线复制异构环境中的数据。该项目不仅非常适合您的用例,而且在当今微服务架构的现代世界中非常有价值,其中服务之间的数据共享至关重要。

通过使用 Envers,您能够提供在线回退解决方案,在您的 ES 集群不可用或过载时为用户提供审计历史数据,而不是给用户一个“服务不可用,稍后再回来”的响应。

无论您做出什么决定,性能都不是唯一令人担忧的因素。您还应该注意用户体验、可扩展性和可靠性;因此,为什么我认为最佳解决方案是将两者配对。


查看完整回答
反对 回复 2022-06-04
?
互换的青春

TA贡献1797条经验 获得超6个赞

您可以通过实现来编写自定义拦截器org.hibernate.EmptyInterceptor。这具有使用实体的新旧快照更新/插入/删除的回调。

有关更多详细信息,请参阅本文


查看完整回答
反对 回复 2022-06-04
  • 2 回答
  • 0 关注
  • 97 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信