使用(强制)第二个JDBC连接到同一个线程

时间:2018-01-30 11:11:17

标签: java hibernate jdbc spring-data

我在MySQL DB的查询中使用流式传输。工作正常,直到我在流媒体中发出另一个查询。这完全可以,并在java.sql.SQLException中解释:

Streaming result set com.mysql.jdbc.RowDataDynamic@16559dec is still active. No statements may be issued when any streaming result sets are open and in use on a given connection. Ensure that you have called .close() on any active streaming result sets before attempting more queries.

因为我真的想在流媒体中间进行第二次查询,显然我只需要使用另一个数据库连接。

那么如何强制在同一个线程中使用另一个连接呢?

我正在使用Spring Data with Hibernate

不要建议一次提取或分页,这不是问题的关键。

编辑:

计划流程:

  • 使用流(使用连接1)
  • 运行查询
  • 对于流中的每一行
    • 在db上执行某些操作(使用连接2)
  • 流式传输结束,连接1关闭

2 个答案:

答案 0 :(得分:1)

所以1个线程{ 1. open conn, 2 - 8. asyncroneously stream, 9. close conn }, { 3. open or use conn, 4. query, 9. close or skip } ??

如果流式传输足够短,请尝试使用连接池

否则,这也是大流更好地作为文件名存储在数据库中的情况(例如使用UUID生成文件名)。然后流式传输可以在数据库之外完成,你可以节流流式传输来阻碍自制的DenialOfService。

问题被重新编辑后。

所以场景是:

void f() {
    open conn
        do a java 8 stream
            g()
    close conn
}

void g() {
    open conn
    ...
    close conn
}

这是可能的,有几种处理方式:使用单个全局连接,使用连接池,事务性或不是cq。自动提交。

对于查询,我猜最重要的是关闭事物。试用资源是不泄漏资源的理想选择。

try (Connection conn = ...) {
    ...
    try (PreparedStatement stm = conn.prepareStatement(sql)) {
        ...
        try (ResultSet rs = stm.executeQuery()) {
            ... the stream
        }
    }
}

上面也关闭了ResultSet,这可能让你陷入困境。

您也可以通过流传递它,它可以访问结果集。 由于Stream也是AutoCloseable,您可能需要在那里调整代码。或者使用CachedRowSet而不是ResultSet。

很抱歉这个不确定的答案。

答案 1 :(得分:0)

我不确定我完全理解你想做什么。我认为你想要流式传输数据,以某种方式转换每个项目,然后坚持结果。如果是这种情况,我相信使用带有注释@Transactional(propagation = Propagation.REQUIRES_NEW)的单独“持久”方法应该可以解决问题。

如果你想要多个处理你的流(比如说,因为你做了一些REST调用,或者由于其他原因你认为可能需要很长时间),你可能要考虑将流元素推送到一个阻塞队列,有多个线程从那里读取,并为每个项目做你需要做的任何事情。