调用 JooQ DSLContext 的 .close() 时连接何时关闭(如果有的话)?

When is a Connection closed when calling JooQ DSLContext's .close(), if at all?

这是我正在编写的使用 JooQ 3.7.0 的 class 代码(无关部分已被删除);注意 DSLContext:

AutoCloseable 特性的使用
public final class JooqPerMethodMetricWriter
    implements PerMethodMetricWriter
{
    private static final Logger LOGGER
        = LoggerFactory.getLogger(JooqPerMethodMetricWriter.class);

    // [snip]

    private final DSLContext jooq;

    public JooqPerMethodMetricWriter(final Connection connection,
        final Instant instant)
        throws IOException
    {
        // [snip]    
        jooq = DSL.using(connection);    
    }

    private void writeCsv(final Configuration configuration)
    {
        // [snip]    

        try (
            final DSLContext context = DSL.using(configuration);
            final Reader reader = Files.newBufferedReader(csvPath);
        ) {

            final Loader<PermethodMetricsRecord> loader = context
                .loadInto(PERMETHOD_METRICS)
                .loadCSV(reader)
                .fields(PERMETHOD_METRICS.fields())
                .execute();
            LOGGER.info("{} lines stored in database", loader.stored());
        } catch (IOException e) {
            throw new RuntimeException("Cannot open CSV for reading", e);
        }
    // BREAKPOINT 1
    }

    @Override
    public void close()
        throws IOException
    {
        jooq.transaction(this::writeCsv);
        jooq.close();
        // BREAKPOINT 2
        Files.delete(csvPath);
    }
        // [snip]    
}

如果相关的话,使用的数据库是 PostgreSQL (9.4.x)。

在上面的代码中,我有两个断点。当我调试时,我看到:

我很困惑。我收到的作为构造函数参数的 Connection 发生了什么?我需要自己 .close() 吗?


附带问题,这次是关于 Loader:我保留默认值,因此 .commitNone();鉴于我 运行 是交易中的加载程序,如果我尝试 .commit<somethingElse>() 代替,例如 .commitAfter(1000)?

,它会有所不同吗?

当前答案

随着 CloseableDSLContext 的引入,当 AutoCloseable 语义再次从更通用的 DSLContext 中删除时,这个问题变得过时了。 jOOQ 3.14 中实施了不兼容的更改,以解决此问题和其他一些问题中表达的混淆,请参阅:

https://github.com/jOOQ/jOOQ/issues/10512

历史答案

DSLContext 在 jOOQ 3.7 的 Java 8 个发行版中变成了 AutoCloseableDSLContext.close() 方法的 Java 文档解释了此 close() 调用的语义:

Close the underlying resources, if any resources have been allocated when constructing this DSLContext.

Some DSLContext constructors, such as DSL.using(String), DSL.using(String, Properties), or DSL.using(String, String, String) allocate a Connection resource, which is inaccessible to the outside of the DSLContext implementation. Proper resource management must thus be done via this close() method.

只有在构建DSLContext时分配的资源才会被释放。不是您传递给 DSLContext 的资源。在你的例子中,你没有在这个 try-with-resources 语句中分配任何资源,所以在它的末尾没有什么可以释放的:

try (DSLContext context = DSL.using(configuration); ...) { ... }

如果您在此处分配一个新的 Connection,情况会有所不同:

try (DSLContext context = DSL.using("jdbc:h2:~/test", "sa", ""); ...) { ... }

关于您的问题:

I'm confused. What happened to the Connection which I have received as a constructor parameter?

没有。你必须自己管理它的生命周期,因为 jOOQ 对你的连接生命周期策略一无所知。

Do I need to .close() it myself?

是的。