在我们的代码中,我们通常使用以下模式:
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是否过于迂腐,或者有更好的方法来关闭数据库连接。
编辑: 添加了删除尝试捕获关闭。
答案 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;
}
});