字段更改的休眠审核日志



如何将实体的更改记录到日志文件中? 考虑一下我有这样的Person

import org.hibernate.envers.Audited;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue;
import javax.persistence.Column;
@Entity
@Audited
public class Person {
@Id
@GeneratedValue
private int id;
private String name;
private String surname;
// add getters, setters, constructors, equals and hashCode here
}

以及更改现有Person的代码

Person p1 = new Person("name-1", "surname-1");
personRepository.save(p1);
Person p2 = personRepository.findOne(1L);
p2.setName("new-name");
personRepository.save(p2);

我怎样才能拥有

  • 旧实体
  • 新实体
  • 字段列表已更改(类似于Diffable的结果)

在我的日志文件中?我知道 envars 可以将更改存储在数据库中,并让我稍后使用AuditReader提取它们,但我喜欢将更改存储在 Json 文件中以将它们发送到第三方应用程序(如 Elastic)。

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

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

让我们以这个基本实体为例:

@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(真)还是0(假)即可自动告诉您这一点。

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

本机查询 ETL

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

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

脱贝齐铵 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 集群不可用或过载时为用户提供审核历史数据,而不是为用户提供"服务不可用,稍后再来"响应。

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

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

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

相关内容

  • 没有找到相关文章

最新更新