关闭语句时mysql随机崩溃

问题描述 投票:0回答:3

我有以下代码:

Statement statement =createStatement();
try (java.sql.ResultSet resultset = statement.executeQuery()) {
    while (resultset.next()) {
        myObject.setProcessingDate(resultset.getDate(1));
        myObject.set...

    }
}finally {
    if (statement != null) {
        statement.close();
    }
}

我知道语句对象应该在 try-with-resource 块中创建,但这是生成的代码。

随机地,我遇到以下异常:

caused by: java.sql.SQLException: Streaming result set com.mysql.cj.protocol.a.result.ResultsetRowsStreaming@9h6d41205 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.
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129)
    at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
    at com.mysql.cj.jdbc.ServerPreparedStatement.realClose(ServerPreparedStatement.java:549)
    at com.mysql.cj.jdbc.ServerPreparedStatement.close(ServerPreparedStatement.java:284)
    at com.zaxxer.hikari.pool.ProxyStatement.close(ProxyStatement.java:76)
    at mypackage.NamedParameterStatement.close(NamedParameterStatement.java:520)

我已经用谷歌搜索过,但没有找到解释为什么我在关闭声明时会遇到此崩溃。 我的结果集对象的“自动”关闭应该在进入finally块之前以及调用statement.close之前调用。 即使我的 resultset.close 没有被调用,我希望 statements.close() 也会检查结果集是否打开并在需要时关闭它。

我是否遗漏了什么或者为什么会出现这个问题?

java mysql jdbc
3个回答
1
投票

尝试使用资源

try-with-resources 语句是声明一个或多个资源的 try 语句。资源是一个对象,程序使用完毕后必须将其关闭

其实已经自动关闭了,不需要手动调用close方法。

回到你的问题!

注意您提供的错误信息

由以下原因引起:java.sql.SQLException:流式处理结果集 com.mysql.cj.protocol.a.result.ResultsetRowsStreaming@9h6d41205 仍处于活动状态。当任何流结果集在给定连接上打开并使用时,不得发出任何语句。

参考这里

流模式有一个限制:当在 MySQL 连接上以流模式打开结果集时,您无法使用同一数据库连接来运行其他查询。

也就是说,当你执行这条语句时,很可能已经有其他结果集处于open阶段了。


0
投票

我已经用谷歌搜索过,但没有找到解释为什么我在关闭声明时会遇到此崩溃。

我不确定你是不是。不是在结束声明时。

结果集对象的“自动”关闭应该在进入finally块之前以及调用statement.close之前调用。

确实如此。

即使我的 resultset.close 没有被调用,我希望 statements.close() 也会检查结果集是否打开并在需要时关闭它。

规格说明

Statement.close()
有这种效果,是的。

再次阅读异常消息,尤其是突出显示的部分:

流式传输结果集 com.mysql.cj.protocol.a.result.ResultsetRowsStreaming@9h6d41205 仍然处于活动状态。 当任何流结果集在给定连接上打开并使用时,不得发出任何语句。

该消息看起来不像是要结束声明。根据您自己的分析,关闭由该代码片段的同一执行创建的

Statement

ResultSet
 之间不应该存在冲突。

我倾向于认为您有一个

different ResultSet

 与属于同一个 
Statement different
 
Connection
 相关联,并且仍然处于活动状态,并且当您尝试创建或执行new 
Statement
,而不是当您尝试关闭语句时(尽管毕竟如果从 
close()
 抛出异常,分析不会受到太大影响)。

此类问题的根源包括

    错误地未能关闭先前获得的
  • ResultSet
  • 在多个线程中同时使用相同的
  • Connection
    ;或
  • 只需使用您的连接尝试在处理另一个查询结果的上下文中执行新查询。
最后一个应该是确定的,因此可以从完整的堆栈跟踪中识别出来。另外两个看起来更有可能是随机的,您很可能会看到源自应用程序代码的不同部分的类似异常。


0
投票
回答了你自己的问题。

因此,明确关闭

Statement

 是一种很好的做法。

确实如此,这里必须补充一下,如果执行隐式闭包,即如果使用

try-with-resources,那么执行close()

时出现的异常应该单独捕获。

AutoClosable

接口
不会自动关闭Statement
,而是用来
隐式关闭它,如上面提到的情况。

现在

//todo,如果无法关闭语句,那么该怎么办?

嗯,这里的原因可能有所不同,但在大多数情况下这没有什么意义,因此可以简单地忽略异常。

© www.soinside.com 2019 - 2024. All rights reserved.