JOOQ 中的提交钩子

Posted

技术标签:

【中文标题】JOOQ 中的提交钩子【英文标题】:Commit hook in JOOQ 【发布时间】:2017-04-26 04:30:32 【问题描述】:

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

我实际上在寻找的是:有没有办法让我使用 JOOQ 的 DSLContext 对象注册提交后挂钩或回调,以便在事务成功提交时运行一些代码?

我知道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 中是否支持提交挂钩?如果是这样,请指出我正确的方向?

【问题讨论】:

尝试结合TransactionProviderRecordListenerExecuteListener。您可以在本地线程中捕获 c/u/d 记录,然后根据最外层事务的完成情况丢弃或发布。 【参考方案1】:

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

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

这不是你要找的。相反,您应该实现自己的TransactionProvider(可能委托给jOOQ 的DefaultTransactionProvider)。然后,您可以在实际提交逻辑之前实现您想要的任何逻辑。

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

【讨论】:

DSLContext 获取TransactionProvider 可能有点混乱,将其转换,然后附加回调,但我已经设法让它正常工作。非常感谢卢卡斯!顺便说一句,期待 3.9 中的新 TransactionListener,但我注意到您只能设置侦听器。为什么不允许在运行时添加它们? @MichaeldeJong 是的,该回调解决方案会很好地工作。为什么您认为您将无法在运行时添加侦听器? 也许我错了(可能),但看看the code,每次你调用这个方法时,它都会替换之前设置的任何内容。我知道这是关于TransactionListenerProvider 而不是TransactionListener,但是如果您想在交易期间添加/注册一个,您需要先获取注册的任何提供者,将您的新提供者添加到调整大小的数组中,然后调用set(TransactionListenerProvider...) 方法对吗? 您自己的TransactionListenerProvider 可以做任何您想做的事情,包括监听您在事务期间添加/注册的一些事件... jOOQ 的 API 中没有任何内容可以阻止您随时覆盖任何内容.你只需要实现你自己的机制

以上是关于JOOQ 中的提交钩子的主要内容,如果未能解决你的问题,请参考以下文章

SVN - 预提交钩子检查代码格式

在 Git 钩子中获取提交消息

Egit 钩子不会被触发

svn配置钩子更新网站目录 每次提交 程序会卡在正在发送文件 有人说是 脚本有问题 手动执行脚本没有问题

Husky 预提交钩子和压缩提交

Git 子模块提交钩子