Jooq事务:如果在事务中抛出异常,连接不会释放到池中

我使用Jooq的HikariCP。 代码:*在Kotlin:

//dataSource is from Hikari DSL.using(dataSource, sqlDialect).transaction { config -> //in create it simply calls dsl.insertInto .... UserRepo.create(User(name="joe"), DSL.using(config)) UserRepo.create(User(name="foo"), DSL.using(config)) } 

一切运行正常。

但是,如果我扔在块,连接不关闭(释放)(尽管事务回滚)。

更新:

我是Java新手,所以这是我的错。 在测试中,我曾经抛出Kotlin的Throwable (而不是Exception ),这是Java代码不能正确处理的部分。

一切正常预期与例外。

正如你已经注意到,考虑到你的问题编辑,JOOQ内部只捕获Exception子类型,而不是可Exception子类型,以影响事务管理。 在DefaultDSLContext.transactionResult0() ,你可以看到下面的代码(从3.9.6版本开始,缩短了这个问题):

 try { provider.begin(ctx); result = transactional.run(ctx.configuration()); provider.commit(ctx); } catch (Exception cause) { // <-- This is the problem ctx.cause(cause); provider.rollback(ctx); if (cause instanceof RuntimeException) { throw (RuntimeException) cause; } else { throw new DataAccessException("Rollback caused", cause); } } 

正如你所看到的,虽然在checked和unchecked 异常之间有区别,但ExceptionThrowable没有区别。

基本原理,Java和Kotlin / Scala

从历史上看,在Java中,没有人真正创建Throwable子类型。 该类型仅作为ExceptionError的常用超类型存在。 所以,假设Throwable是上面的任一个, Error类型通常不应该被任何客户端/库代码捕获。

这种假设被诸如Kotlin和Scala之类的语言所无效,这些语言不会继承这一点,诚然,从Java早期的时候就有点奇怪的API设计。 没有理由为什么用户定义的异常不应该直接扩展Throwable 。 不幸的是,现状意味着你不能使用throwables,你必须抛出异常。

窃听器

这当然是jOOQ中的一个错误,应该修复: https : //github.com/jOOQ/jOOQ/issues/6608

因为它在行为方面有些后退不相容,所以只能在一个小的版本中修正,即3.10