有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java When是调用JooQ DSLContext时关闭的连接。close(),如果有的话?

下面是我正在编写的一个类的代码,该类使用JOOQ3.7.0(不相关的部分已被剥离);注意DSLContextAutoCloseable特性的用法:

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)

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

  • 在第一个断点处,configuration.connectionProvider().acquire().isClosed()为false
  • 在第二个断点处, jooq.configuration().connectionProvider().acquire().isClosed()也是错误的

我很困惑。作为构造函数参数接收的Connection发生了什么?我需要自己动手吗


附带问题,这次关于Loader:我保留默认值,因此.commitNone();假设我在一个事务中运行加载程序,那么如果我尝试使用.commit<somethingElse>(),例如.commitAfter(1000),会有什么不同吗


共 (1) 个答案

  1. # 1 楼答案

    当前答案

    随着^{}的引入,这个问题变得过时了,因为AutoCloseable语义再次从更通用的DSLContext中删除。jOOQ 3.14中实施了不兼容变更,以解决此问题和其他几个问题中表达的困惑,请参见:

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

    历史答案

    DSLContext随着jooq3.7的java8发行版而变得AutoCloseable^{}方法的Javadoc解释了这个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?