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

时间:2017-09-25 18:31:01

标签: transactions kotlin 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部分代码无法正确处理的。

通过常规例外,一切都按预期工作。

1 个答案:

答案 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);
    }
}

正如您所看到的,虽然已检查和未检查例外之间存在区别,但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