2016-12-11 147 views
1

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

我基本上在寻找的是:有没有办法让我用JOOQ的DSLContext对象注册post-commit钩子或回调,所以我可以在事务成功提交时运行一些代码?

我知道了ExecuteListenerExecuteListenerProvider接口的,但据我可以告诉void end(ExecuteContext ctx)方法(这是所谓的生命周期使用的结束)提交事务时不叫。它在每个查询之后都被调用。

下面是一个例子:让我相信这不是为commit钩子

Pre insert. 
End method triggered. 
Post insert. 

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(); 
} 

这似乎总是打印。

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

+1

尝试组合'TransactionProvider','RecordListener'和'ExecuteListener'。您可以在本地线程中捕获c/u/d记录,并根据最外层事务的完成情况丢弃或发布。 –

回答

1

ExecuteListener SPI是听单查询执行,即这个生命周期:

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

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

请注意,jOOQ 3.9还将提供一个新的TransactionListener SPI(see #5378)以方便此操作。

+0

从'DSLContext'中获取'TransactionProvider',投射它,然后附加一个回调可能有点麻烦,但是我已经设法使它正常工作。非常感谢Lukas!顺便说一句,期待在3.9中新的'TransactionListener',但我注意到你只能设置监听器。为什么不允许在运行时添加它们? –

+0

@MichaeldeJong是的,该回调解决方案将很好地工作。为什么你认为你将无法在运行时添加监听器? –

+0

也许我错了(可能),但看看[代码](https://github.com/jOOQ/jOOQ/commit/4e1f458e6c1f0e1e7e695f84890956fb8cc30ecd#diff-5b0bc82019c25f8bf90f60d2b2177b17R806),每次你调用这个方法时,它会取代任何之前设置。我知道它是关于'TransactionListenerProvider'而不是'TransactionListener'的,但是如果你想在事务中添加/注册一个,你需要首先获取任何提供者的注册信息,然后将新的信息添加到一个调整大小的数组中,然后调用'set(TransactionListenerProvider ...)'方法吧? –