Java 如果基础连接已关闭,为什么对于PreparedStatements,isClosed()方法不返回true?

Java 如果基础连接已关闭,为什么对于PreparedStatements,isClosed()方法不返回true?,java,sql,jdbc,Java,Sql,Jdbc,正如标题所说,我想知道为什么一个prepared statements.isClosed()方法在关闭底层流(使用JDBC)后会返回false 输出 false false 但是,如果尝试调用set方法或execute,则会得到以下结果: java.sql.SQLException: org.apache.commons.dbcp.DelegatingCallableStatement with address: "SQLServerCallableStatement:32" is close

正如标题所说,我想知道为什么一个prepared statements.isClosed()方法在关闭底层流(使用JDBC)后会返回false

输出

false
false
但是,如果尝试调用set方法或execute,则会得到以下结果:

java.sql.SQLException: org.apache.commons.dbcp.DelegatingCallableStatement with address: "SQLServerCallableStatement:32" is closed.
at org.apache.commons.dbcp.DelegatingStatement.checkOpen(DelegatingStatement.java:137)
at org.apache.commons.dbcp.DelegatingPreparedStatement.setInt(DelegatingPreparedStatement.java:120)
at org.apache.commons.dbcp.DelegatingPreparedStatement.setInt(DelegatingPreparedStatement.java:120)
at com.ipti.ptl.common.messagetable.MessageHandlerTest.someTest(MessageHandlerTest.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606) .....

这可能是DBCP库的一个bug,不过我必须看一下JDBC规范。您是否尝试过为您的驱动程序使用原生JDBC
PreparedStatement

编辑

查看MySQL连接器源代码(可用),它看起来像是
Connection.close()
的实现实际上关闭了与连接相关的所有语句。因此,当使用MySQL JDBC驱动程序时,
PreparedStatement.isClosed()
将在连接关闭时返回true。不过,我不太确定JDBC规范对此有何规定

在您的情况下,我不确定DBCP库是否将对
isClosed()
的调用委托给底层驱动程序,这就是为什么我建议删除这个额外的层,看看会发生什么。如果DBCP中有bug,我会报告它。如果您使用的底层驱动程序中存在错误,我也会报告。假设这确实是一个bug

编辑2

根据这些评论,JDBC 4.1规范说明(第9.4.4.1节):

连接。关闭

应用程序调用方法Connection.close()以指示它已 已完成使用连接。从给定语句创建的所有语句对象 当关闭连接的方法时,连接对象将被关闭 对象被调用


因此,我预计该声明将真正结束。因此,DBCP库或正在使用的MS SQL Server驱动程序中存在错误。

打开另一个新连接后,PreparedStatement可能仍然可以使用。我不太明白,PreparedStatement是从连接构造的。如果我重新创建连接,请准备一条语句。。“这与第一次准备好的声明有区别吗?”欧文莫说得很好,但如何区别呢
PreparedStatement
没有
setConnection
方法…只是新建连接()。executePreparedStatement(以前的PreparedStatement)?您的标题和问题不一样。关闭连接确实会关闭PreparedStatement。JDBC规范是这样说的,您的异常证明了这一点。你的问题是为什么PreparedStatement.isClosed()在某些特定的实现中没有这样说。我正在使用JDBC,我给它加了标签,但我会在问题中明确提到它以供澄清。这不是我的意思。您正在使用包装JDBC驱动程序的ApacheCommonsDBCP(根据堆栈跟踪)。您实际使用的是哪个驱动程序?org.apache.commons.dbcp.poolgDriver再说一遍,您没有明白我的意思:您看到的异常是由dbcp引发的,我理解这一点。但是,底层JDBC驱动程序可能会也可能不会在这种情况下抛出。因此,它可能是DBCP中的一个bug。您实际使用的是哪个数据库?MS SQL Server 2012:jdbc:apache:commons:dbcp:如果我再次误解,请原谅,我不太清楚您的问题是什么。。。
java.sql.SQLException: org.apache.commons.dbcp.DelegatingCallableStatement with address: "SQLServerCallableStatement:32" is closed.
at org.apache.commons.dbcp.DelegatingStatement.checkOpen(DelegatingStatement.java:137)
at org.apache.commons.dbcp.DelegatingPreparedStatement.setInt(DelegatingPreparedStatement.java:120)
at org.apache.commons.dbcp.DelegatingPreparedStatement.setInt(DelegatingPreparedStatement.java:120)
at com.ipti.ptl.common.messagetable.MessageHandlerTest.someTest(MessageHandlerTest.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606) .....