【发布时间】:2017-10-12 03:31:49
【问题描述】:
我需要审核我们应用程序中某些实体的更改,并且正在考虑使用 JaVers。我喜欢 JaVers 提供的对查询审计数据的支持。 Hibernate Envers 看起来不错,但它会将数据存储在同一个数据库中。
这是我的要求:
- 异步日志记录 - 将性能影响降至最低
- 将审计数据存储在不同的数据库中 - 也是性能原因
据我所知,JaVers 不是为上述目的而设计的,但似乎可以适应实现上述目的。方法如下:
- JaVers 实际上允许将数据存储在不同的数据库中。您可以真正提供与任何数据库的连接。这不是它的意图,但它有效。下面的代码(注意 connectionProvider 可以提供到任何数据库的连接):
'
final Connection dbConnection =
DriverManager.getConnection("jdbc:mysql://localhost:3306/javers", "root", "root");
ConnectionProvider connectionProvider = new ConnectionProvider() {
@Override
public Connection getConnection() {
//suitable only for testing!
return dbConnection;
}
};
JaversSqlRepository sqlRepository = SqlRepositoryBuilder
.sqlRepository()
.withConnectionProvider(connectionProvider)
.withDialect(DialectName.MYSQL).build();
- 可以通过将 JaVers 提交的执行移到线程/执行器中来实现异步。挑战在于,如果执行时间过长,则可能是对象在记录之前发生了变化。我可以在这里想到两种解决方案:
- 我们可以创建对象的快照(例如,将其序列化为 JSON 等)并将其传递给线程以记录它。
- 我们提供了 Javers Repository 的自定义实现,它处理当前线程中的差异,然后将 Snapshot 对象传递到另一个线程中持久化。这样,我们只需要在应用程序线程中读取 DB,并在 Auditing 线程中写入(这通常在性能方面成本更高)。
问题:
- 我在这里遗漏了什么吗?这行得通吗?
- JaVers 是否支持创建对象的快照,然后可以将其移动到另一个线程。它在内部某个地方执行此操作,所以也许我们可以使用它。
仅供参考:与该问题无关,但以下是我能想到的其他一些挑战以及我打算如何解决它们:
- 由于不在同一个事务中进行审计,如果事务失败,它会使审计回滚变得复杂。所以我们只需要审核成功提交的对象。我打算通过使用 Hibernate 拦截器、监听
afterTransactionCompletion并仅提交由该事务更新的对象来做到这一点。 - 对于延迟加载的对象,我可以看到,如果我们在事务完成后尝试访问它们,可能是无法访问延迟加载的道具(因为会话也可能关闭) - 不知道如何解决这个问题,但这可能不是问题,因为我认为我们正在加载大多数道具。
【问题讨论】:
-
异步提交已在 3.12.0 版本中发布