清理JDBC资源时最佳做法是什么?为什么?我保持示例简短,因此只是清理ResultSet。
finally
{
if(rs != null)
try{ rs.close(); } catch(SQLException ignored) {}
}
与
finally
{
try{ rs.close(); } catch(Exception ignored) {}
}
我个人赞成第二种选择,因为它有点短。对此的任何意见都非常感谢。
答案 0 :(得分:10)
如今,JDK 7为您提供了清理资源的最简单方法:
String query = "select COF_NAME, PRICE from COFFEES";
try (Statement stmt = con.createStatement()) {
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
String coffeeName = rs.getString("COF_NAME");
float price = rs.getFloat("PRICE");
System.out.println(coffeeName + ", " + price);
}
}
try语句确保在语句结束时关闭每个资源。见http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
答案 1 :(得分:4)
正如其他人所指出的,JDBC资源(语句,结果集等)很少null
。如果是,那么您手上的更大的问题比NullPointerException
更多。在这方面,NullPointerException
将帮助提醒您JDBC驱动程序的严重问题。如果您的JDBC驱动程序实际上为您提供null
引用,则在调用close()
之前对null
进行典型检查会无提示地隐藏问题。
同样,并非所有JDBC驱动程序都严格遵循规范。例如,某些驱动程序在关联ResultSet
关闭时不会自动关闭Statement
。因此,您必须确保您明确关闭ResultSet
和其Statement
(叹息)。
在实践中,我发现这种技术很有用(尽管它不是最漂亮的):
PreparedStatement statement = connection.prepareStatement("...");
try {
ResultSet results = statement.executeQuery();
try {
while (results.next()) {
// ...
}
} finally {
results.close();
}
} finally {
statement.close();
}
此技术可确保执行每个close()
语句,从ResultSet
开始并向外工作。如果驱动程序为您提供NullPointerException
引用,仍然会抛出null
,但我允许这样做是出于开头所解释的原因。如果任何SQLException
语句失败,我仍然会抛出close()
个(我认为这是件好事 - 我想知道是否出现问题)。
答案 2 :(得分:3)
我发现你的第二个(不常见)版本没问题。
null
,因此在极少数情况下会发生NPE。所以我认为这里没有性能问题。rs = null
唯一的缺点 - 如果我们要关闭多个资源,那么我们必须为每个资源添加一个try / catch,如果我们想要关闭尽可能多的资源。否则,我们将使用第一个null
输入catch子句,这可能会导致未泄漏的泄漏。
所以它看起来像那样:
finally {
try{rs.close(); }catch(Exception ignored){}
try{stmt.close();}catch(Exception ignored){}
try{conn.close();}catch(Exception ignored){}
}
......这仍然是可读和可理解的。但是,根据永远不会改变一种常见的模式 - 我会坚持使用老式的方法来首先测试null
并在关闭时捕捉SQLException
。
答案 3 :(得分:2)
我倾向于使用以下方法。我认为检查null
是好的,因为它显示了你的意图,即你确实意识到在极少数情况下这些对象可能为空。 (空检查也比创建NullPointerException
更快。)我也认为记录异常是好的,而不是吞下它们。在close
失败的情况下,我想知道它并将其存储在我的日志文件中。
finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
LOG.warn("Failed to close rs", e);
}
}
if (st != null) {
try {
st.close();
} catch (SQLException e) {
LOG.warn("Failed to close st", e);
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
LOG.warn("Failed to close conn", e);
}
}
}
如果您要经常这样做,而不是一遍又一遍地复制和粘贴此代码,请使用静态方法创建一个实用程序类来关闭ResultSet,Statement和Connection。
使用DBUtils,您可以非常简洁地执行此清理,如下所示:
finally {
DBUtils.closeQuietly(rs);
DBUtils.closeQuietly(st);
DBUtils.closeQuietly(conn);
}
答案 4 :(得分:2)
public static void close(Statement... statements) {
for (Statement stmt : statements) {
try {
if (stmt != null)
stmt.close();
} catch (SQLException se) {
}// nothing we can do
}
}
public static void close(Connection conn) {
try {
if (conn != null)
conn.close();
} catch (SQLException se) {
}// nothing we can do
}
public static void close(ResultSet rs) {
try {
if (rs != null)
rs.close();
} catch (SQLException se) {
}// nothing we can do
}
答案 5 :(得分:1)
这是我对JDK 6的方法。如果你有JDK 7+,你最好使用我在这里描述的方法https://stackoverflow.com/a/9200053/259237
private void querySomething() {
Connection connection = null;
PreparedStatement statement = null;
ResultSet rs = null;
try {
// get connection
// prepare statement
// execute query
// and so on
} catch (SQLException e) {
throw new MyException("Error while talking to database", e);
} finally {
close(connection, statement, rs);
}
}
// useful because you probably have more than one method interacting with database
public static void close (Connection connection, Statement statement, ResultSet rs) {
if (rs != null) {
try { rs.close(); } catch (Exception e) { _logger.warning(e.toString()); }
}
if (statement != null) {
try { statement.close(); } catch (Exception e) { _logger.warning(e.toString()); }
}
if (connection != null) {
try { connection.close(); } catch (Exception e) { _logger.warning(e.toString()); }
}
}
答案 6 :(得分:0)
ResultSet rs = //initialize here
try {
// do stuff here
} finally {
try { rs.close(); }
catch(SQLException ignored) {}
}
答案 7 :(得分:0)
如果您正在编写长时间运行的应用程序,则应考虑连接池。
Apache DBCP项目为您完成了很多这方面的工作。您还可以查看类似Spring JDBC或Hibernate的内容。
Spring的东西使用了对象池,并添加了一些非常好的方法来抽象出JDBC nastiness。
答案 8 :(得分:0)
protected void closeAll(){
closeResultSet();
closeStatement();
closeConnection();
}
protected void closeConnection(){
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
/*Logger*/
}
connection = null;
}
}
protected void closeStatement() {
if (stmt != null) {
try {
ocstmt.close();
} catch (SQLException e) {
/*Logger*/
}
ocstmt = null;
}
}
protected void closeResultSet() {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
/*Logger*/
}
rs = null;
}
}