3

在我们的代码中,我们通常使用以下模式:

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 是否过于迂腐,或者是否有更好的方法来关闭数据库连接。

编辑:添加了删除的 try catch 关闭。

4

6 回答 6

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")
于 2010-12-09T12:59:37.327 回答
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 并没有将这一点(即使用库或您自己的方法)识别为正确关闭资源并向您发出警告。在这种情况下,它显然是一个误报。因此,必须确保它是您收到的唯一警告,然后禁用该方法的特定警告。

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

于 2011-08-18T14:26:47.077 回答
4

是的,有更好的方法。

创建一个将关闭包装在 try/catch 中的静态方法:

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
}
于 2010-12-09T12:54:50.510 回答
1

是的,你应该把你的 close 封装在一个 try 块中,但是有一个更聪明的方法。

try {
    Connection c = getConnection();
    try {
        //do stuff
    } finally {
        c.close();
    }
} catch (SQLException e) {
    //Catch exceptions
}
于 2010-12-09T13:03:20.053 回答
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
    }
}
于 2010-12-09T12:55:17.997 回答
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 如何捕获异常?

于 2013-05-14T14:45:13.393 回答