Java关闭连接和findbugs

时间:2010-12-09 12:51:44

标签: java database 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()可以抛出异常,因此无法保证关闭连接。 findbugs是否过于迂腐,或者有更好的方法来关闭数据库连接。

编辑: 添加了删除尝试捕获关闭。

6 个答案:

答案 0 :(得分:6)

已经有一个实用程序可以完成@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")

答案 1 :(得分:6)

你真正想做的是将“精英绅士”的答案与@edu.umd.cs.findbugs.annotations.SuppressWarnings( "OBL_UNSATISFIED_OBLIGATION" )注释结合起来。如果你以下面的方式完成关闭方法,那么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无法识别这一点(即使用库或您自己的方法)正确关闭资源并向您发出警告。在这种情况下,它显然是false positive。因此,必须确保它是您获得的唯一警告,然后禁用该方法的特定警告。

@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警告。

答案 2 :(得分:4)

是的,有更好的方法。

创建一个静态方法,在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
}

答案 3 :(得分:1)

是的,你应该把你的关闭封装在一个try块中,但是有一种更聪明的方式。

try {
    Connection c = getConnection();
    try {
        //do stuff
    } finally {
        c.close();
    }
} catch (SQLException e) {
    //Catch exceptions
}

答案 4 :(得分:0)

没有更好的方法,但如果你想确保抓住所有东西,请修改你的模式:

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
    }
}

答案 5 :(得分:0)

你可以通过使用像Spring JDBCTemplate这样的东西来避免这一切,它可以为你正确地封装所有的打开/关闭逻辑,简化你的代码,使它更清晰,更容易阅读(以及更可能是正确的)。

一个例子,从表中读取一些列到键值对列表(是的,丑陋的,但很容易理解):

        List<Map<String, Object>> resultList = jdbcTemplate.query(query,
                new RowMapper<Map<String, Object>>() {
                    @Override
                    public Map<String, Object> mapRow(ResultSet rs,
                            int rownum) throws SQLException {
                        Map<String, Object> row = new HashMap<String, Object>();
                        int colIndex = 0;
                        row.put(CONTENTID_KEY, rs.getInt(++colIndex));
                        row.put(CONTENTTYPEID_KEY, rs.getInt(++colIndex));
                        row.put(DESCRIPTION_KEY, rs.getString(++colIndex));
                        row.put(CODE_KEY, rs.getString(++colIndex));
                        return row;
                    }
                });

有关异常处理,请参阅spring jdbcTemplate how to catch exception?