Jooq 事务:如果事务中抛出异常,则连接不会释放到池中
Posted
技术标签:
【中文标题】Jooq 事务:如果事务中抛出异常,则连接不会释放到池中【英文标题】:Jooq transactions: connections are not released to pool, if exception thrown in transaction 【发布时间】:2018-03-06 19:40:56 【问题描述】:我正在将 HikariCP 与 Jooq 一起使用。 代码: *在 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 部分代码正确处理。
常规异常情况下一切正常。
【问题讨论】:
【参考方案1】:正如您所注意到的,鉴于您的问题编辑,jOOQ 在内部仅捕获 Exception
子类型,而不是 Throwable
子类型以影响事务管理。在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);
如您所见,虽然选中和未选中异常之间存在区别,但 Exception
和 Throwable
之间没有区别。
基本原理,Java vs Kotlin / Scala
从历史上看,在 Java 中,没有人真正创建 Throwable
子类型。该类型仅作为Exception
和Error
的通用超类型存在。因此,假设Throwable
是上述任何一种,并且Error
类型通常不应被任何客户端/库代码捕获。
这种假设在 Kotlin 和 Scala 等语言中无效,它们没有继承这一点,诚然,早期 Java 时代的 API 设计有点奇怪。用户定义的异常没有理由不直接扩展Throwable
。不幸的是,现状意味着你不能使用 throwable,你必须抛出异常。
错误
这肯定是 jOOQ 中的一个错误,应该修复: https://github.com/jOOQ/jOOQ/issues/6608
由于它在行为方面有点向后不兼容,因此只会在次要版本中修复,即 3.10
【讨论】:
以上是关于Jooq 事务:如果事务中抛出异常,则连接不会释放到池中的主要内容,如果未能解决你的问题,请参考以下文章