When is a Connection closed when calling JooQ DSLC

2019-08-14 22:25发布

Here is the code of a class which I am writing which uses JooQ 3.7.0 (the irrelevant parts have been stripped); note the uses of the AutoCloseable feature of DSLContext:

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]    
}

If relevant at all, the database used is PostgreSQL (9.4.x).

In the code above, I have two breakpoints. When I debug, I see that:

  • at the first breakpoint, configuration.connectionProvider().acquire().isClosed() is false...
  • at the second breakpoint, jooq.configuration().connectionProvider().acquire().isClosed() is also false.

I'm confused. What happened to the Connection which I have received as a constructor parameter? Do I need to .close() it myself?


Side question, this time with regards to the Loader: I leave the defaults, therefore .commitNone(); given that I run the loader within a transacation, would it make a difference at all if I tried and .commit<somethingElse>() instead, for instance .commitAfter(1000)?

1条回答
兄弟一词,经得起流年.
2楼-- · 2019-08-14 22:44

DSLContext became AutoCloseable with the Java 8 distributions of jOOQ 3.7. The DSLContext.close() method's Javadoc explains the semantics of this close() call:

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.

Only resources allocated when you constructed the DSLContext will be released. Not resources that you passed to the DSLContext. In your case, you are not allocating any resources in this try-with-resources statement, so there is nothing to be released at the end of it:

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

This would be different if you allocated a new Connection right there:

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

Regarding your questions:

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

Nothing. You must govern its lifecycle yourself as jOOQ doesn't know anything about your connection lifecycle strategy.

Do I need to .close() it myself?

Yes.

查看更多
登录 后发表回答