Java 休眠字段的审核日志';改变

Java 休眠字段的审核日志';改变,java,hibernate,spring-data,hibernate-envers,audit-logging,Java,Hibernate,Spring Data,Hibernate Envers,Audit Logging,如何将实体的更改记录到日志文件中? 考虑一下我有人>代码>。 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 { @I

如何将实体的更改记录到日志文件中? 考虑一下我有<代码>人>代码>。

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 p1 = new Person("name-1", "surname-1");
personRepository.save(p1);
Person p2 = personRepository.findOne(1L);
p2.setName("new-name");
personRepository.save(p2);
我怎么能有

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

在我的日志文件中?我知道它可以将更改存储在db中,让我稍后使用
AuditReader
将其提取出来,但我喜欢将更改存储在Json文件中,以将其发送给第三方应用程序(如Elastic)。

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


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

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

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

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

@Entity
@Audited(withModifiedFlag = true)
public class Person {
  @Id
  @GeneratedValue
  private Integer id;
  private String name;
}
当您启用带有ModifiedFlag的
功能时,这会通知Envers向该实体的审核表中添加一些额外的元数据列,因此该实体的审核表基本上如下所示:

+----+------+----------+-----+---------+
| ID | name | name_MOD | REV | REVTYPE |
+----+------+----------+-----+---------+
这里的好处是,如果您使用某些流程直接从表中导出和流式传输数据,那么您不再需要实际区分当前行和前一行以了解更改的内容;模式只需查看关联的
\u MOD
列是
1
(true)还是
0
(false),即可自动告诉您这一点

从这一点上,你有几个选择

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

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

脱苄菌 Debezium项目是处理数据复制的一种很好的方法。它的一个强大优势是,它允许用户跨完全适合您的模型的异构平台执行此操作

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

例如:

  • Hibernate执行
    插入到Person(?,)值(?,)
  • Hibernate Envers执行
    插入到Person\u AUD(…)值(…)
  • 数据库将该操作写入重做/事务日志
  • Debezium注意到日志已写入,读取条目
  • Debezium为
    个人用户生成一个插入事件(表已订阅)
  • 该事件的任何注册利益方都会收到并处理该事件
  • 在(5)中,存在转换/加载代码来接收插入事件并生成JSON输出并将其发送到ES

    收尾 通过使用Debezium,您可以在一个极其高效的庄园中跨异构环境有效地离线复制数据。该项目不仅非常适合您的用例,而且在当今微服务体系结构的现代世界中也非常有价值,因为服务之间的数据共享至关重要

    通过使用Envers,您能够提供在线回退解决方案,以便在ES群集不可用或过载时向用户提供审核历史数据,而不是向用户提供“服务不可用,请稍后再来”响应


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

    弹性搜索是否必须作为当前事务的一部分立即更新,或者您是否能够在最终流程中以最终一致性模式更新弹性搜索。事实上,我喜欢登录到一个文件中,这样LogStash就可以读取它并将其推入到Elastic中。你们的问题太广泛了。让Envers做它自己的事情,然后在审计表中构建数据的JSON表示怎么样?问题是我不喜欢Envers给我的数据库增加更多的负载。此外,Envers强制我查询数据库以获得更改。这意味着我可怜的DB有更多的负载。我有零钱吗?我只看到了应该刷新到db的实体。@mLotfizad因为你有新旧状态,你可以像你的想法一样计算差异,我在旧项目中使用了Debezium。但是,目前,我无法将新技术添加到项目堆栈中。任务的定义生动地迫使我将差异记录在日志文件中。