【问题标题】:Jooq transactions: connections are not released to pool, if exception thrown in transactionJooq 事务:如果事务中抛出异常,则连接不会释放到池中
【发布时间】: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 部分代码正确处理。

常规异常情况下一切正常。

【问题讨论】:

    标签: transactions kotlin jooq


    【解决方案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 vs Kotlin / Scala

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

    这种假设在 Kotlin 和 Scala 等语言中无效,它们没有继承这一点,诚然,早期 Java 时代的 API 设计有点奇怪。用户定义的异常没有理由不直接扩展Throwable。不幸的是,现状意味着你不能使用 throwable,你必须抛出异常。

    错误

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

    由于它在行为方面有点向后不兼容,因此只会在次要版本中修复,即 3.10

    【讨论】:

      猜你喜欢
      • 2017-03-11
      • 2016-10-24
      • 2019-04-30
      • 2017-02-19
      • 2017-04-07
      • 2017-03-17
      • 2016-11-16
      • 2014-11-30
      • 1970-01-01
      相关资源
      最近更新 更多