调用 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)。
在上面的代码中,我有两个断点。当我调试时,我看到:
- 在第一个断点处,
configuration.connectionProvider().acquire().isClosed()
为假...
- 在第二个断点处,
jooq.configuration().connectionProvider().acquire().isClosed()
是 也是 错误。
我很困惑。我收到的作为构造函数参数的 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 个发行版中变成了 AutoCloseable
。 DSLContext.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?
是的。
这是我正在编写的使用 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)。
在上面的代码中,我有两个断点。当我调试时,我看到:
- 在第一个断点处,
configuration.connectionProvider().acquire().isClosed()
为假... - 在第二个断点处,
jooq.configuration().connectionProvider().acquire().isClosed()
是 也是 错误。
我很困惑。我收到的作为构造函数参数的 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 个发行版中变成了 AutoCloseable
。 DSLContext.close()
方法的 Java 文档解释了此 close()
调用的语义:
Close the underlying resources, if any resources have been allocated when constructing this
DSLContext
.Some
DSLContext
constructors, such asDSL.using(String)
,DSL.using(String, Properties)
, orDSL.using(String, String, String)
allocate aConnection
resource, which is inaccessible to the outside of theDSLContext
implementation. Proper resource management must thus be done via thisclose()
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?
是的。