题
我已经做码的审查(大多是使用的工具,如置的代)的一个我们的宠物项目和置的代标记的以下代码错误(伪):
Connection conn = dataSource.getConnection();
try{
PreparedStatement stmt = conn.prepareStatement();
//initialize the statement
stmt.execute();
ResultSet rs = stmt.getResultSet();
//get data
}finally{
conn.close();
}
错误的是,这个代码可能不会释放资源。我想通了,结果,并声明不会关闭,所以我封闭他们在最后:
finally{
try{
rs.close()
}catch(SqlException se){
//log it
}
try{
stmt.close();
}catch(SqlException se){
//log it
}
conn.close();
}
但我遇到了上述模式中的许多项目(从相当多的公司),并没有一个是关闭的结果集或声明。
你有没有麻烦的结果集和声明没有被关闭的时关闭连接?
我只发现了 此 它指Oracle有问题的关闭结果集时关闭连接(我们使用Oracle数据库,因此我更正).java。sql。api说什么连接。close()如果是的话,为什么不试.
解决方案
仅关闭连接而不是结果集的一个问题是,如果您的连接管理代码使用连接池, connection.close()
只会将连接放回池中。此外,某些数据库在服务器上有一个游标资源,除非明确关闭,否则将无法正确释放。
其他提示
即使连接已关闭,我在Oracle中未解决的ResultSet也遇到了问题。我得到的错误是
"ORA-01000: maximum open cursors exceeded"
所以:总是关闭你的ResultSet!
您应该始终显式关闭所有JDBC资源。正如Aaron和John已经说过的那样,关闭连接通常只会将它返回到池中,并不是所有的JDBC驱动程序都以完全相同的方式实现。
这是一个可以在finally块中使用的实用方法:
public static void closeEverything(ResultSet rs, Statement stmt,
Connection con) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
}
}
if (con != null) {
try {
con.close();
} catch (SQLException e) {
}
}
}
在这种情况下,Oracle会向您提供有关打开游标的错误。
根据: http://java.sun的.com / JavaSE的/ 6 /文档/ API / JAVA / SQL / Statement.html
看起来重用一个语句将关闭所有打开的结果集,关闭一个语句将关闭所有结果集,但我没有看到关闭连接的任何内容将关闭它创建的任何资源。
所有这些细节都留给JDBC驱动程序提供程序。
明确地关闭所有内容总是最安全的。我们写了一个util类,用try {xxx} catch(Throwable {}包装所有东西,这样你就可以调用Utils.close(rs)和Utils.close(stmt)等,而不必担心关闭扫描的异常会抛出
ODBC桥可以产生一个存储器泄漏一些ODBC drivers.
如果你使用一个很好的JDBC驱动程序,那么你应该不会有任何问题与关闭连接。但有2个问题:
- 不你知道如果你有一个很好的司机?
- 你会用其他JDBC驱动程序的未来?
最好的做法是关闭了这一切。
我工作在一个大J2EE网环境。我们有几个数据库可连接到一个请求。我们开始获得合乎逻辑的僵局,在我们的一些应用程序。问题是,如下:
- 用户请求页
- 服务器连接的数据库1
- 服务器选择对DB1
- 服务器"关闭"连接的数据库1
- 服务器连接的数据库2的
- 陷入僵局!
这发生于2个原因,我们正在经历远远高的交通量比正常和J2EE规默认情况下实际上不闭上你的连接,直到线完成的执行。因此,在上面的例步骤4永远不会实际上关闭了连接,即使他们是正确关闭在最后。
为了解决这个问题,你,你必须使用资源引用的web.xml 你的数据库连接并设res共享的范围unsharable.
例如:
<resource-ref>
<description>My Database</description>
<res-ref-name>jdbc/jndi/pathtodatasource</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Unshareable</res-sharing-scope>
</resource-ref>
我肯定已经看到了未封闭的ResultSet的问题,以及一直关闭它们会有什么不妥,对吧?需要记住这样做的不可靠性是转移到为您管理这些细节的框架的最佳理由之一。它可能在您的开发环境中不可行,但我很幸运使用Spring来管理JPA事务。打开连接,语句,结果集以及编写过于复杂的try / catch / finally块(在finally块中使用try / catch块!)的混乱细节再次关闭它们只会消失,留下你真的完成了一些工作。我强烈建议您迁移到这种解决方案。
在Java中,语句(而非Resultsets)与Oracle中的游标相关联。最好关闭打开的资源,因为JVM和系统资源可能会发生意外行为。
此外,一些JDBC池框架池语句和连接,因此不关闭它们可能不会在池中将这些对象标记为空闲,并导致框架中出现性能问题。
一般情况下,如果某个对象上有close()或destroy()方法,则有理由对其进行调用,并且忽略它是由您自己承担的。