在 try-with-resources 块之外流式传输 JOOQ 结果时,我是不是会冒 JDBC 连接泄漏的风险?

Posted

技术标签:

【中文标题】在 try-with-resources 块之外流式传输 JOOQ 结果时,我是不是会冒 JDBC 连接泄漏的风险?【英文标题】:Do I risk a JDBC connection leak when streaming JOOQ results outside a try-with-resources block?在 try-with-resources 块之外流式传输 JOOQ 结果时,我是否会冒 JDBC 连接泄漏的风险? 【发布时间】:2016-06-04 03:47:44 【问题描述】:

我有一个 JOOQ 查询,我想避免同时实现所有记录。 (但是,我可以将所有从它们创建的 bean 对象联合具体化。)

我有以下简单的方法来加载数据:

public List<CustomerInfo> getCustomers() 
    return dslContext
                .selectFrom(CUSTOMER)
                // <-- note the missing .fetch()
                .stream()
                .map(CustomerInfo::new)
                .collect(Collectors.toList());

这会在任何情况下导致 JDBC 连接泄漏吗? (例如CustomerInfo::new 中的异常)

【问题讨论】:

【参考方案1】:

我已经尝试过找到一种方法来注册一个可靠的流“完成”钩子,该钩子会在完整的流消耗或任何异常时触发,但不幸的是,这是不可能的:Register a Stream "completion" hook

所以,确实,您显示的代码不正确。操作“惰性”流(或Cursor)的正确方法是使用 try-with-resources 语句。以下两个是等价的:

// Using a Stream
try (Stream<CustomerRecord> stream = dslContext.selectFrom(CUSTOMER).stream()) 
    return stream.map(CustomerInfo::new).collect(Collectors.toList());


// Using a Cursor
try (Cursor<CustomerRecord> cursor = dslContext.selectFrom(CUSTOMER).fetchLazy()) 
    return cursor.stream().map(CustomerInfo::new).collect(Collectors.toList());

还要注意ResultQuery.stream() javadoc:

这本质上与 fetchLazy() 相同,但不是返回 Cursor,而是返回 Java 8 Stream。客户端应确保正确关闭 Stream,例如在 try-with-resources 语句中

【讨论】:

以上是关于在 try-with-resources 块之外流式传输 JOOQ 结果时,我是不是会冒 JDBC 连接泄漏的风险?的主要内容,如果未能解决你的问题,请参考以下文章

try-with-resources 关闭异常中的流控制

java9新特性-增强的try-with-resources块

你是否还在写try-catch-finally?来使用try-with-resources优雅地关闭

由编译器完成的 Java try-with-resource 实现

基础笔记10(IO 1.7try-with-resource)

在 try-with-resource 中手动关闭