在 JOOQ 中提交挂钩

Commit hook in JOOQ

我在后端网络服务中使用 JOOQ 已有一段时间了。在许多这样的服务中,在将数据持久化到数据库之后(或者更确切地说,在成功提交数据之后),我们通常希望向 Kafka 写入一些关于持久化记录的消息,以便其他服务知道这些事件。

我本质上要寻找的是:有没有办法让我用 JOOQ 的 DSLContext 对象注册一个 post-提交挂钩或回调,这样我就可以 运行事务成功提交时的一些代码?

我知道 ExecuteListenerExecuteListenerProvider 接口,但据我所知 void end(ExecuteContext ctx) 方法(据说用于生命周期结束使用)不是提交事务时调用。不过每次查询后都会调用它。

这是一个例子:

 public static void main(String[] args) throws Throwable {
    Class.forName("org.postgresql.Driver");
    Connection connection = DriverManager.getConnection("<url>", "<user>", "<pass>");
    connection.setAutoCommit(false);

    DSLContext context = DSL.using(connection, SQLDialect.POSTGRES_9_5);
    context.transaction(conf -> {
        conf.set(new DefaultExecuteListenerProvider(new DefaultExecuteListener() {
            @Override
            public void end(ExecuteContext ctx) {
                System.out.println("End method triggered.");
            }
        }));

        DSLContext innerContext = DSL.using(conf);
        System.out.println("Pre insert.");
        innerContext.insertInto(...).execute();
        System.out.println("Post insert.");
    });

    connection.close();
}

似乎总是打印:

Pre insert.
End method triggered.
Post insert.

让我相信这不是为提交钩子设计的。

是否有 JOOQ 大师可以告诉我 JOOQ 中是否支持提交挂钩?如果是这样,请指出正确的方向?

ExecuteListener SPI 正在侦听单次查询执行 的生命周期,即:

innerContext.insertInto(...).execute();

这不是您要查找的内容。相反,您应该实现自己的 TransactionProvider (possibly delegating to jOOQ's DefaultTransactionProvider)。然后,您可以在实际提交逻辑之前实现您想要的任何逻辑。

请注意,jOOQ 3.9 还将提供一个新的 TransactionListener SPI (see #5378) 来促进这一点。