Java关闭连接和findbugs
在我们的代码中,我们通常使用以下模式:Java关闭连接和findbugs,java,database,findbugs,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 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中包装结束的静态方法:
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
}
没有更好的方法,但如果您想确保捕获所有内容,请将您的模式修改为:
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
}
}
已经有一个实用程序实现了@duffymo提到的功能:来自Apache
DbUtils.close(ResultSet)代码>
DbUtils.close(语句)代码>
DbUtils.close(连接)代码>
更新 下面是一个例子:
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是一个唠叨者,那么您可以添加以下注释(在方法的顶部)
是的,你应该将你的收盘价封装在试牌中,但有一种更聪明的方法
try {
Connection c = getConnection();
try {
//do stuff
} finally {
c.close();
}
} catch (SQLException e) {
//Catch exceptions
}
您真正想做的是将“精英绅士”的答案与
@edu.umd.cs.findbugs.annotations.SuppressWarnings(“OBL\u未满足的义务”)
注释结合起来。FindBugs似乎只有在您以以下方式使用完整的收尾方法时才会感到高兴(顺便说一句,这是这样做的首选顺序):
这是非常冗长的,如果出于对腕管的热爱,您可能不想这样做,因此您应该使用DBUtils.closequity()
方法(或者创建您自己的调用)。但是,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警告。您可以通过使用Spring JDBCTemplate之类的工具来避免整个问题,它为您正确封装了所有打开/关闭逻辑,简化了代码,使其更清晰、更易于阅读(而且更可能是正确的) 例如,将表中的一些列读入键值对列表(是的,很难看,但很容易理解):
List resultList=jdbcTemplate.query(查询,
新的行映射器(){
@凌驾
公共地图地图行(结果集rs,
int rownum)抛出SQLException{
Map row=newhashmap();
int-colIndex=0;
row.put(CONTENTID_键,rs.getInt(++colIndex));
put(CONTENTTYPEID_键,rs.getInt(++colIndex));
row.put(DESCRIPTION_KEY,rs.getString(++colIndex));
put(CODE_KEY,rs.getString(++colIndex));
返回行;
}
});
有关异常处理,请参见conn.close在catch中,已更新问题以添加此内容。@Stephen:总有更好的方法;只是乍一看并不总是很明显。-1所以把试扣放回去。为了简洁而编辑它应该是非实质性的。您的代码验证程序是否存在未捕获异常问题,或者连接不能保证关闭?是否添加了try-catch。Findbugs在上述方面存在问题,因为如果在conn.close()期间引发异常,连接(可能)将保持打开状态。javac应该会抱怨该代码。如果你做了一些愚蠢的事情,比如说,用
null
分配conn
,那么你就有了一个潜在的NPE。@Jim我建议你看看我的答案,因为我认为它比你当前选择的答案更好。使用资源进行尝试可以解决所有问题并解决问题;)这当然更整洁,因为无论在何处使用连接,都会减少重复捕捉。但是我相信findbugs仍然不会高兴,因为关闭时的异常将意味着它将保持打开状态。//打印或日志堆栈跟踪
否,您应该抛出异常(可能是SQLException
)。您不一定要抛出异常。虽然无法关闭连接很烦人,但它不一定会导致事务回滚之类的事情。@Tom Hawtin-不,这个方法的全部目的是防止异常发生。你误解了这个问题。@duffymo,令人惊讶的是为什么会有没有解释的否决票。我认为实际上应该禁止。FindBugs似乎仍然会抱怨如果你使用DBUtils来关闭连接。@ArtB,你是安静地关闭连接还是使用DBUtil简单关闭(捕获异常)?我使用的是DBUtils.closeQuiety()
。答案是添加注释@edu.umd.cs.findbugs.annotations.SuppressWarnings(“OBL\u未满足的义务”)
。我希望这能得到投票,让人们看到它,而不是仅仅停留在“更多评论”链接中。也许我应该加上它作为一个单独的答案?这不是“更聪明的(原文如此)”;如果抛出异常,连接将泄漏。如果我错了,请纠正我,但如果在内部try块中抛出异常,finally块仍将运行。“连接将泄漏”的唯一方法是关闭语句本身抛出异常。
...
}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
}
}
}
}
@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 );
}
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;
}
});