与JaVers进行异步审核

时间:2017-10-12 03:31:50

标签: java javers

我需要审核应用程序中某些实体的更改,并考虑使用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读取,并在审计线程中进行编写(通常性能更高)。

问题:

  • 我在这里错过了什么?这可行吗?
  • JaVers是否支持创建对象的快照,然后可以将其移动到另一个线程。它在内部的某个地方做,所以也许它是我们可以使用的东西。

仅供参考:与此问题无关,但这里有一些我能想到的其他挑战以及我计划如何解决这些挑战:

  • 由于未在同一事务中进行审计,就好像事务失败一样,它使审计回滚变得复杂。因此,我们只需要审核成功提交的对象。我打算通过使用Hibernate Interceptor,监听afterTransactionCompletion并仅提交由该事务更新的对象来实现。
  • 如果是延迟加载的对象,我可以看到,如果我们在交易完成后尝试访问它们,可能是因为无法访问延迟加载的道具(作为会话)可能也会关闭) - 不知道如何解决这个问题,但这可能不是问题,因为我认为我们正在加载渴望最多的道具。

1 个答案:

答案 0 :(得分:1)

有趣的问题。 首先是精神恍惚。所有JaVers核心模块都旨在将审计数据与应用程序数据分离。如您所述,用户提供了一个供JaVers使用的ConnectionProvider。它可以是您想要的任何数据库。

不适用于多个数据库的是用于SQL的Spring集成模块,因此javers-spring-jpajavers-spring-boot-starter-sql。它们只涵盖了最常见的场景,因此应用程序和JaVers的数据库相同。

你是对的缺乏异步提交。幸运的是,它只能在JaversCore中实现,而无需更改存储库。

API可以是:

CompletableFuture<Commit> javers.commitAsync(..., Executor);

首先,Javers将拍摄用户对象的快照,速度很快,因此可以在当前线程中完成。

然后,DB读取(加载最新快照)和DB写入(插入新快照)可以异步完成(提交给给定的Executor)。

正如您所提到的,它需要新的数据库事务方法。我们计划实施提交提款功能,因此应用程序可以在主数据库回滚后撤销JaVers的提交。见https://github.com/javers/javers/issues/588