Java/JDBC:发生异常时关闭数据库连接的最佳设计模式
我是Java新手(我正在使用Java6)。我的所有Java POJO和servlet都使用了下面的设计模式,通过GlassFish 3.1.2 web服务器访问Oracle 11G数据库 当所有可用进程(或会话,不确定区别是什么)都被消耗时,我会遇到间歇性数据库错误(ORA-12519),这让我觉得应用程序没有释放这些进程 看看下面的设计模式,是否有更好的方法确保在发生异常时释放到数据库的JDBC连接?例如,如果(conn!=null)conn.close(),我是否也应该放置Java/JDBC:发生异常时关闭数据库连接的最佳设计模式,java,database,oracle,jdbc,Java,Database,Oracle,Jdbc,我是Java新手(我正在使用Java6)。我的所有Java POJO和servlet都使用了下面的设计模式,通过GlassFish 3.1.2 web服务器访问Oracle 11G数据库 当所有可用进程(或会话,不确定区别是什么)都被消耗时,我会遇到间歇性数据库错误(ORA-12519),这让我觉得应用程序没有释放这些进程 看看下面的设计模式,是否有更好的方法确保在发生异常时释放到数据库的JDBC连接?例如,如果(conn!=null)conn.close(),我是否也应该放置if捕捉块内的代码
if代码>捕捉块内的代码?或者,有更好的设计模式吗?提前感谢您的任何意见/提示
public String MyFunction() throws Exception {
Connection conn;
CallableStatement cs;
try {
Context context = new InitialContext();
DataSource ds = (DataSource)context.lookup("jdbc/MyPool");
conn = ds.getConnection();
cs = conn.prepareCall( "{call my_sproc (?)}" );
cs.registerOutParameter(1, Types.VARCHAR);
cs.execute();
String outParam = cs.getString(1);
if ( conn != null ) // close connection
conn.close();
} catch (Exception e) {
outParam = "an error occurred";
}
return outparam;
}
始终使用块释放资源
当try块退出时,finally块始终执行。这确保即使发生意外异常,也会执行finally块
在这一行,conn
不能为空。在Java 6之前,最流行的模式是:
Connection conn = null;
try {
// initialize connection
// use connection
} catch {
// handle exception
} finally {
if (conn != null) {
try { conn.close(); } catch (Exception e) { /* handle close exception, quite usually ignore */ }
}
}
使用Java7这将减少其构造的麻烦。上面的代码可以更改为更短的代码
try (Connection conn = createConnection()) {
// use connection
} catch {
// handle exception
}
// close is not required to be called explicitly
JavaSE7支持资源试用功能。这将为您生成最终结果
finally块将关闭try中分配的资源。就像你在c中使用关键字一样#
但是,用户正在使用JavaSE6。。。请参见其他用户的选项:)
重要提示:使用的语句也应该关闭。我更喜欢另一种更优雅的方式,而不是:
} finally {
if (conn != null) {
try {
conn.close();
} catch (Exception e) {
/* handle close exception, quite usually ignore */
}
}
}
您可以使用DbUtils.closequilley:谢谢Kazekage,如果连接尚未打开或其他原因,finally块中的conn.close()
代码行是否会出错?如果是这样,我不应该在finally块中使用上面的If(conn!=null)
语句吗?如果您怀疑conn.close()
将再次给出错误,请用try catch finally
环绕该语句。@ggkmath yes您需要测试conn!=空
;如果ds.getConnection()
引发异常,则可以为null。无论您是否怀疑,都需要将close()
放入try/catch/finally
;否则,该方法必须将其包含在其throws
子句中,这是不好的。感谢这个变量,当您说“直到Java 6”时,您的意思是“直到并包括Java 6”(这就是我正在使用的)?我想是的。另外,当您说“通常被忽略”时,您是否仅指finally块中的try…catch
(即if(conn!=null)conn.close();
始终存在,对吗?)?为什么人们在关闭连接时通常忽略处理finally块中的异常?是的,connection.close()
中的异常通常会被忽略,或者最多会被记录,但不会以任何其他方式处理:)我不知道为什么;我从来没有见过close抛出异常。我只是想说清楚,因为不管发生什么最终都会执行,所以我不需要关闭try块内的连接,对吗?我可以在代码中的finally块中关闭一次连接。是吗?是的,正如我在模板中所显示的,连接通常只在最后关闭。我没有阅读,但用户变量也谈到了使用资源进行尝试。我将在1分钟内确认这一点,但我猜您需要关闭语句。Doesn似乎不是通用的。你看,我错了。apidocs for不表示关闭连接
会关闭其语句
;但请注意,关闭结果集需要关闭。JDBC规范规定,当连接关闭时,语句将关闭(JDBC 4.1规范第9.4.4.1节)。另外,Connection.close()
的JavaDoc声明“立即释放此连接对象的数据库和JDBC资源”JDBC资源是从连接(即语句)创建的任何对象。请注意,关闭结果集和语句也是一种好的做法。这里有一个有用的链接(请参阅Stefan Schweizer在链接中的回复,以了解良好的设计模式):
try (Connection conn = createConnection()) {
// use connection
} catch {
// handle exception
}
// close is not required to be called explicitly
} finally {
if (conn != null) {
try {
conn.close();
} catch (Exception e) {
/* handle close exception, quite usually ignore */
}
}
}