【问题标题】:JOOQ and resource handlingJOOQ 和资源处理
【发布时间】:2018-06-05 03:17:49
【问题描述】:

我使用 JOOQ 来查询我的关系数据库,我最近一直在研究连接处理,这让我有点困惑。我试过阅读 JavaDoc 和这个:When is a Connection closed when calling JooQ DSLContext's .close(), if at all?,但它为我创造了更多的 FUD。

目前我的代码是这样做的:

try (final Connection cn = pool.getConnection()) {
    DSLContext dsl = DSL.using(cn, MARIADB);
    // query stuff
}

本质上,我将 JOOQ 视为根本不进行连接处理的查询器。这段代码我从来没有遇到过问题。

但是,我确实收到了来自 IntelliJ 的警告,说 DSLContext 是 AutoClosable 并且应该由 try-with-resources 处理。我知道在这种情况下不必这样做,但我的第一个问题是“可以吗?”。用这个代替上面的代码是否安全:

try (final DSLContext dsl = DSL.using(pool.getConnection(), MARIADB)) {
    // query stuff
}

另一个 StackOverflow 帖子说,当您使用其中一种帮助方法创建 DSLContext 时,您需要在 DSLContext 上使用 close()。但是如果你只是传入了 Connection 对象呢? close() 还会关闭我的连接吗?

我还发现 DSL 有另一个 using() 允许您分配整个数据源。所以我也可以这样做:

final DSLContext dsl = DSL.using(pool, MARIADB);

然后完全忽略所有的 try-with-resources。这里有什么取舍?有吗?

IntelliJ 进一步抱怨了具有 AutoClosable 接口(继承自 Query)的 UpdateQuery。是否有必要关闭我的查询?我一直只是调用 execute() 并毫无问题地关闭了底层连接。

【问题讨论】:

    标签: java intellij-idea connection jooq try-with-resources


    【解决方案1】:

    我正在寻找的是能够满足这四个要求的代码

    1. 它使用正确的资源管理
    2. 它使用 JOOQ
    3. 在 IDE 中打开了 try-with-resources 警告
    4. 没有警告

    上面的各种代码都没有满足这些要求中的至少一项。但最终连接处理并不重要,因为 JOOQ 中的查询类也会产生大量警告。

    最好的方法确实是关闭警告,但是对于 JOOQ 来说,专门使用 Intellij 的排除规则。 Lukas 链接的页面上的评论中提到了如何执行此操作 (https://blog.jooq.org/2015/12/02/a-subtle-autocloseable-contract-change-between-java-7-and-java-8/)。

    我只需要记住为 JOOQ 课程以正确的方式做事 :)

    【讨论】:

      【解决方案2】:

      目前我的代码是这样做的:

      try (final Connection cn = pool.getConnection()) {
          DSLContext dsl = DSL.using(cn, MARIADB);
          // query stuff
      }
      

      这是正确的用法。

      本质上,我将 JOOQ 视为根本不进行连接处理的查询器。

      这是一个正确的假设。

      但是,我确实收到 IntelliJ 的警告,说 DSLContext 是 AutoClosable 并且应该由 try-with-resources 处理

      许多 IDE 都会执行此检查,但通常最好将其关闭。在 Java 8+ 中,您不能合理地期望 AutoCloseable 真正需要关闭。一个这样的例子是Stream,它是AutoCloseable,它确实包含资源,但大多数情况下不包含。

      This was a subtle API change in Java 8,导致最好关闭 IDE 中的此警告(或者您可以指定例外)。

      您的问题:

      用这个代替上面的代码是否安全:

      try (final DSLContext dsl = DSL.using(pool.getConnection(), MARIADB)) {
        // query stuff
      }
      

      是的,你可以这样做。 DSLContext.close() 调用只会关闭由DSLContext 创建的资源。在你的情况下,它没有任何效果。

      为了记录,创建了资源丰富的 DSLContexts,例如DSL.using(url, username, password)

      然后完全忽略所有的 try-with-resources。这里有什么取舍?有吗?

      所有这些都与资源无关。

      IntelliJ 进一步抱怨了具有 AutoClosable 接口(继承自 Query)的 UpdateQuery。是否有必要关闭我的查询?我一直只是调用 execute() 并毫无问题地关闭了底层连接。

      1. 关闭该警告! :-)
      2. 调用Query.keepStatement(true) 时,查询可能会很丰富

      【讨论】:

      • “是的,你可以这样做。DSLContext.close() 调用只会关闭由 DSLContext 创建的资源。”。这非常令人困惑。如果 DSLContext 只会关闭由它创建的资源,那么答案应该是否定的?因为我自己从池中抓取了 Connection 并没有自己关闭它。所以这段代码应该会导致资源泄漏
      • 我不想关闭该警告的原因是它确实可以帮助解决讨厌的小错误。我曾经写过的最大错误是没有从 AWS sdk 中关闭 S3Object,因为我不知道它需要关闭。
      • “如果 DSLContext 只会关闭它创建的资源,那么答案应该是否定的?” - 你可以这样做,但它不会有任何效果。尝试在任何 Java 8 流上调用 Stream.close()。我不认为这个 jOOQ 案例应该比 Java 8 Streams 更令人困惑...... “因为我自己从池中获取了连接,并且没有自己关闭它” 然后 应该关闭连接。 “所以这段代码应该会导致资源泄漏” - 是的,但不是你的 jOOQ 代码可以,你的连接池客户端代码可以!
      • 是的,我想需求和设计约束的结合无法让我在这里拥有我想要的东西。我认为 Java 在描述 Autoclosable 的合同时是正确的,我认为 JOOQ 在实现它时是正确的,而 IntelliJ 在提供警告时我认​​为是正确的。它只是设计约束的不幸组合。不能吃我的蛋糕也吃:)
      • 是的,它可以,这就是我现在正在使用的。它是我认为我能满足的所有要求的最接近的。它并不完美,因为我可能会不小心弄乱 JOOQ 代码,但因为我一直在编写该代码,所以我并不太害怕。我在下面写了答案,以便为其他人总结。
      猜你喜欢
      • 2020-12-09
      • 1970-01-01
      • 2013-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多