JOOQ 中的提交钩子
Posted
技术标签:
【中文标题】JOOQ 中的提交钩子【英文标题】:Commit hook in JOOQ 【发布时间】:2017-04-26 04:30:32 【问题描述】:我在后端 Web 服务中使用 JOOQ 已经有一段时间了。在其中许多服务中,在将数据持久化到数据库之后(或者更好地说,在成功提交数据之后),我们通常希望向 Kafka 写入一些关于持久化记录的消息,以便其他服务知道这些事件。
我实际上在寻找的是:有没有办法让我使用 JOOQ 的 DSLContext
对象注册提交后挂钩或回调,以便在事务成功提交时运行一些代码?
我知道ExecuteListener
和ExecuteListenerProvider
接口,但据我所知,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 中是否支持提交挂钩?如果是这样,请指出我正确的方向?
【问题讨论】:
尝试结合TransactionProvider
、RecordListener
和ExecuteListener
。您可以在本地线程中捕获 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 中的提交钩子的主要内容,如果未能解决你的问题,请参考以下文章