下面是我正在编写的一个使用JooQ 3.7.0的类的代码(不相关的部分已经被剥离);注意AutoCloseableDSLContext特性的用法:

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发生了什么事?我自己需要吗?
另一个问题是,这次关于.close():我保留默认值,因此Loader;假设我在一个事务中运行加载程序,如果我尝试改为.commitNone(),比如.commit<somethingElse>(),会有什么不同吗?

最佳答案

在jOOQ 3.7的Java 8发行版中,DSLContext变成了AutoCloseableDSLContext.close()方法的Javadoc解释了这个close()调用的语义:
如果在构造此DSLContext时已分配了任何资源,请关闭基础资源。
一些DSLContext构造函数,例如DSL.using(String)DSL.using(String, Properties)DSL.using(String, String, String)分配Connection资源,这些资源在DSLContext实现外部是不可访问的。因此,必须通过这种close()方法进行适当的资源管理。
只有在构建DSLContext时分配的资源才会被释放。不是传递给DSLContext的资源。在您的情况下,您没有在这个try-with-resources语句中分配任何资源,因此在它的末尾没有要释放的内容:

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

如果您在此处分配了一个新的Connection,则会有所不同:
try (DSLContext context = DSL.using("jdbc:h2:~/test", "sa", ""); ...) { ... }

关于你的问题:
我很困惑。作为构造函数参数收到的连接怎么了?
没有什么。您必须自己管理它的生命周期,因为jOOQ对您的连接生命周期策略一无所知。
我需要自己关闭它吗?
对。

07-26 01:54