我正在和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部分代码无法正确处理的。
通过常规例外,一切都按预期工作。
答案 0 :(得分: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中,没有人真正创建Throwable
个子类型。该类型仅作为Exception
和Error
的常见超类型存在。因此,假设Throwable
是上述任何一种,Error
类型通常不应被任何客户端/库代码捕获。
这种假设被像Kotlin和Scala这样的语言无效,这些语言没有继承这一点,从早期的Java时代开始就是一种奇怪的API设计。用户定义的异常没有理由不直接扩展Throwable
。不幸的是,现状意味着你不能使用throwables,你必须抛出异常。
这肯定是jOOQ中的一个错误,应该修复: https://github.com/jOOQ/jOOQ/issues/6608
由于它在行为方面有些向后兼容,因此只会在次要版本中修复,即3.10