日期:2014-05-16 浏览次数:20526 次
finally {
if (con != null) {
con.close();
}
if (stmt != null) {
stmt.close();
}
}
在这段代码中,关闭资源时,出现了次序错误
而有关多个异常的处理的代码绝大多数是按照下面的结构实现
try {
} catch (SQLException e) {
} catch (IOException e) {
} catch (XXXException e) {
} finally {
}
如果没有打开数据库连接事务,代码可能是这样的:
try {
...
} catch (SQLException e) {
} catch (IOException e) {
} catch (XXXException e) {
} finally {
con.close()
}
在这种情况下,数据库发生死锁的可能性为零。 try {
...
con.commit();
} catch (SQLException e) {
con.rollback();
} catch (IOException e) {
} catch (XXXException e) {
} finally {
con.close();
}
在这样混合了多种异常的代码中,如果发生了非SQLException异常,极有可能出现死锁的情况,一旦发生非SQLException异常,事务既没有提交,也没有回滚,虽然JDBC关闭了数据库连接,但是在数据库服务器中,数据库事务仍然是打开的。在使用SQL Server2000时,这一点可以通过对SQL Server2000的企业管理器/管理/当前活动/锁/对象等部分观察而得到结论。其它的数据库产品是否也有类似的情况?这段代码看似优雅,但缺乏健壮性;从代码的健壮性考虑,应当将代码拆分成三个try{}catch(XXXException
e){}finally{}。如果希望维持代码的优雅,则应当在这段代码的实现细节上多下点功夫,比如多增加几个boolean变量,看代码能否执行到下一个阶段。 try{
...
} catch (java.lang.ClassCastException ex) {
throw new SQLException("java.lang.ClassCastException: " + ex.getMessage(), ex.getCause());
} catch (NumberFormatException ex) {
throw new SQLException("NumberFormatException: " + ex.getMessage(), ex.getCause());
} catch (IOException ex) {
throw new SQLException("IOException: " + ex.getMessage(), ex.getCause());
} finally {
pstmt.close();
}
相关的资源打开和关闭,分散在整个ProcessVO的多个方法中,但在关闭资源时,严格注意次序。对于数据库连接(或者叫会话)、事务、PreparedStatement对象、Statement对象、ResultSet对象等资源,ProcessVO中遵守的次序是:先打开,后关闭,后打开,先关闭。 /**
* 提交事务。
*
* @throws SQLException
*/
public void commit() throws SQLException {
if (!con.isClosed()) {
if (!autoCommit) {
try {
con.commit();
autoCommit = true;
con.setAutoCommit(autoCommit);
failCommit = false;
con.close();
} finally {
if (failCommit) {
rollback();
}
}
}
}
}
/**