概述
变更日志提供了一种内置机制,用于记录变更(插入、更新和删除事件)。有 4 个接口,我们可以选择性地实现它们来控制机制的各个部分。默认情况下,我们可以使用 @ChangeLog
注释实体 Bean,并将变更以 JSON 格式记录到日志记录器中。
与 @History
有重叠,后者是一种以数据库为中心的方法。与 @ChangeLog
不同,@History
是事务性的,并且不能被绕过。
注意事项
SqlUpdate、CallableSql 和通过 Update 进行的批量更新不包含在变更日志中。
入门
步骤 1:确定插入的默认值
插入可以默认包含在变更日志中或不包含,这取决于应用程序。在使用 @ChangeLog 注释实体 Bean 时最好先考虑这一点,因为我们可以选择覆盖默认行为。
默认情况下,插入会被包含。DatabaseConfig.setChangeLogIncludeInserts(boolean)
可用于控制默认行为。这也可以通过 application.properties 设置。
ebean.changeLogIncludeInserts=false
步骤 2:添加 @ChangeLog
将 @ChangeLog
注释添加到应启用变更日志记录的所有实体 Bean。
@ChangeLog
@Entity
public class Address {
...
/**
* Only include updates if specific properties are changed.
*/
@ChangeLog(updatesThatInclude = {"name","dateOfBirth"})
@Entity
public class Customer {
...
/**
* Override the default behaviour for inserts - INCLUDE, EXCLUDE or DEFAULT.
* In this case exclude inserts from the change log.
*/
@ChangeLog(inserts = ChangeLogInsertMode.EXCLUDE)
@Entity
public class Customer {
...
步骤 3:实现 ChangeLogPrepare
如果我们跳过此步骤并且不提供 ChangeLogPrepare 实现,则会使用“无操作”实现,并且用户上下文信息(用户 ID、用户 IP 地址等)将保持未填充状态。
通常,我们实现 ChangeLogPrepare,获取用户上下文信息(如用户 ID 和用户 IP 地址),并将其设置在变更集中。返回 true 表示处理继续,并且变更集在后台线程中传递给 ChangeLogListener。
如果我们希望在前景中进行日志记录,则可以在准备方法中调用日志记录并返回 false(这意味着变更集不会在后台线程中传递给 ChangeLogListener)。
class MyChangeLogPrepare implements ChangeLogPrepare {
@Override
public boolean prepare(ChangeSet changes) {
// get user context information typically from a
// ThreadLocal or similar mechanism
String currentUserId = ...;
changes.setUserId(currentUserId);
String userIpAddress = ...;
changes.setUserIpAddress(userIpAddress);
changes.setSource("myApplicationName");
// add arbitrary user context information to the
// userContext map
changes.getUserContext().put("some", "thing");
return true;
}
}
步骤 4:注册 ChangeLogPrepare 实现
如果启用了类路径扫描,则可以自动检测 ChangeLogPrepare 的实现(就像找到实体 bean 一样)。也就是说,如果启用了扫描,则我们不需要显式注册 ChangeLogPrepare 实现,而是会找到并实例化它。
如果未使用扫描或 ChangeLogPrepare 实现具有依赖项,并且其实例化应在 Ebean 外部执行,那么我们使用 DatabaseConfig 显式注册它。
// example code explicitly registering the ChangeLogPrepare implementation
MyChangeLogPrepare changeLogPrepare = ...;
DatabaseConfig config = new DatabaseConfig();
...
// register explicitly here
config.setChangeLogPrepare(changeLogPrepare);
Database database = DatabaseFactory.create(config);
...
步骤 5:配置日志记录
ChangeLogListener 的默认实现将事件记录到 io.ebean.ChangeLog
。通常,我们会配置日志记录,以便这些日志转到一个单独的日志。
在下面的 logback xml 配置中,追加器 CHANGE_LOG
用于将更改事件记录到此单独的日志。
<appender name="CHANGE_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>log/changeLog.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>log/changeLog.log.%d{yyyy-MM-dd}</FileNamePattern>
<MaxHistory>90</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{HH:mm:ss.SSS} %msg%n</pattern>
</encoder>
</appender>
<logger name="io.ebean.ChangeLog" level="TRACE" additivity="false">
<appender-ref ref="CHANGE_LOG"/>
</logger>