Java关闭连接和findbugs
在我们的代码中,我们通常使用以下模式:
Connection conn; try{ conn = getConnection(); //Do databasey stuff }catch(Exceptions that get thrown){ }finally{ try{ conn.close(); }catch(SQLException ex){ logger.error("Failed to cleanup database connection",ex); } }
然而,findbugs不喜欢这个。 由于conn.close()可以抛出exception,因此无法保证关闭连接。 findbugs是否过于迂腐或是否有更好的方法来关闭数据库连接。
编辑:添加删除尝试捕获关闭。
你真正想做的是将“The Elite Gentleman”的答案与@edu.umd.cs.findbugs.annotations.SuppressWarnings( "OBL_UNSATISFIED_OBLIGATION" )
注释结合起来。 如果你以下面的方式完成关闭方法(这是btw这样做的首选顺序),FindBugs似乎只是很高兴:
... }finally{ try{ resultSet.close(); }catch( SqlException e ){ //log error }finally{ try{ statement.close(); }catch( SqlException e ){ //log error }finally{ try{ connection.close(); }catch( SqlException e ){ //log error } } } }
这是非常冗长的,如果没有其他原因,你可能不想这样做,因为你应该使用DBUtils.closeQuietly()
方法(或创建自己的,你的调用)。 但是,FindBugs无法识别这一点(即使用库或您自己的方法)正确关闭资源并向您发出警告。 在这种情况下,这显然是误报 。 因此,必须确保它是您获得的唯一警告,然后禁用该方法的特定警告。
@edu.umd.cs.findbugs.annotations.SuppressWarnings( "OBL_UNSATISFIED_OBLIGATION" ) public void doStuff( final Connection connection ){ try{ //Do databasey stuff }catch( SqlException e ){ //throw a glorious exception.... }finally{ DbUtils.closeQuietly( resultSet ); DbUtils.closeQuietly( statement ); DbUtils.closeQuietly( connection ); }
这样,您可以使用几行代码清理资源,并避免使用FindBugs警告。
已经有一个实用程序可以完成@duffymo提到的:Apache的DbUtils 。
-
DbUtils.close(ResultSet);
-
DbUtils.close(Statement);
-
DbUtils.close(Connection);
APIDocs显示所有可用的方法。
更新
这是一个例子:
import org.apache.commons.dbutils; Connection conn; try{ conn = getConnection(); //Do databasey stuff } catch(Exception e){ //throw a glorious exception.... } finally{ DbUtils.closeQuietly(conn); //This hides the SQLException thrown by conn.close(); //or //DbUtils.close(conn); }
更新:正如ArtB所建议的那样,如果您最终关闭资源和连接并且findBugs是一个唠叨,您可以添加以下注释(在方法之上)。
@edu.umd.cs.findbugs.annotations.SuppressWarnings("OBL_UNSATISFIED_OBLIGATION")
是的,有更好的方法。
创建一个静态方法,在try / catch中包装close:
public class DatabaseUtils { public static void close(Connection c) { try { if (c != null) { c.close(); } } catch (SQLException e) { // print or log stack trace } } // same for Statement and ResultSet }
是的,你应该将你的关闭封装在try块中,但是有一种更聪明的方式。
try { Connection c = getConnection(); try { //do stuff } finally { c.close(); } } catch (SQLException e) { //Catch exceptions }
没有更好的方法,但如果你想确保捕获所有内容,请将模式修改为:
Connection conn; try{ conn = getConnection(); //Do databasey stuff }catch(Exceptions that get thrown){ }finally{ try { conn.close(); } catch (SQLException se) { log.error("database problems..."); // do more stuff if you need to } }
您可以通过使用Spring JDBCTemplate之类的东西来避免整个过程,它可以为您正确封装所有打开/关闭逻辑,简化代码,使其更清晰,更易于阅读(以及更可能是正确的)。
例如,将表中的某些列读入键值对列表(是的,丑陋的,但很容易理解):
List
对于exception处理,请参见spring jdbcTemplate如何捕获exception?