2010-12-09 3 views
3

우리가 일반적으로 다음과 같은 패턴을 사용 :자바 폐쇄 연결 및 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()는 예외를 throw 할 수 있기 때문에 연결이 닫히지 않을 수 있습니다. findbugs가 너무 과장 적이거나 데이터베이스 연결을 종료하는 더 좋은 방법입니다.

편집 : 삭제 된 try catch가 닫힌 상태로 추가되었습니다.

+1

-1 따라서 try catch를 다시 넣으십시오. 간결하게 편집하면 중요하지 않습니다. 코드 검사기에서 포착되지 않은 예외 또는 연결이 닫히지 않을 수있는 문제가 있습니까? –

+0

try catch를 추가했습니다. Findbugs는 conn.close() 도중 예외가 발생하면 연결이 열려 있기 때문에 위의 문제가 있습니다. – Jim

+0

javac가 해당 코드에 대해 불평해야합니다. 만약 당신이 뭔가 잘못하면,'conn'을'null'로 지정하면 잠재적 인 NPE가 생깁니다. –

답변

6

는 "엘리트 신사"를 @edu.umd.cs.findbugs.annotations.SuppressWarnings("OBL_UNSATISFIED_OBLIGATION") 주석과의 답을 결합하는 것입니다. FindBugs는 행복 할 것 같다 당신이 만약 (BTW 그렇게 선호 순서입니다) 다음과 같은 방식으로 방법의 완전한 폐쇄 : 매우 자세한이며, 당신은 아마 경우 싶지 않아

... 
}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 경고를 피할 수 있습니다.

+1

+1 주석을 추가합니다. –

4

네, 더 좋은 방법이 있습니다.

시도/캐치에 가까운 랩 정적 메서드 만들기 :

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

이것은 연결이 사용되는 곳마다 반복적으로 잡기를 줄여주기 때문에 더 깔끔합니다. 그러나 findbugs가 클로즈의 예외로서 여전히 행복하지 않을 것이라는 확신은 이것이 여전히 열려 있음을 의미합니다. – Jim

+0

'// print 또는 log stack trace' 아니요, 예외를 던져야합니다 (가능한 'SQLException'). –

+0

반드시 예외를 throw하려는 것은 아닙니다. 연결을 닫지 못하는 것은 성가신 일이지만 반드시 트랜잭션 롤백과 같은 일을 일으키지 않아야합니다. – Jim

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

conn.close가 캐치 안에 있으며, 이것을 추가 할 질문이 업데이트되었습니다. – Jim

+1

분명히 ** ** 더 좋은 방법입니다. –

+0

@Stephen : 항상 좋은 방법이 있습니다. 언뜻보기에는 항상 분명하지 않습니다. – darioo

6

@duffymo가 말한 것을 수행하는 유틸리티가 있습니다. Apache에서 DbUtils. DbUtils.close(Connection);

APIDocsDbUtils.close(Statement);

  • DbUtils.close(ResultSet);
    • 모든 가능한 방법을 보여준다.

      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") 
      
  • +0

    나에게서. 나는 그것을 한 번 선물했다. 나는 또한 downvoted 얻었다. – duffymo

    +0

    @duffymo, 이유가없는 downvotes가있는 이유는 놀랍습니다. –

    +0

    나는 그것이 실제로 금지되어야한다고 생각한다. – EJP

    1

    예, 닫기 블록을 try 블록에 캡슐화해야하지만 더 복잡한 방법이 있습니다. 당신이 정말로 원하는 어떤 일을 할

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

    "이상한 [sic]"이 아닙니다. 예외가 발생하면 연결이 유출됩니다. –

    +1

    내가 틀렸다고 정정하되, 내부 try 블록에 예외가 발생하면 finally 블록이 계속 실행됩니다.close 문 자체가 예외를 throw하는 경우 "연결 누설"유일한 방법입니다. –

    0

    모든 열기/닫기 로직을 ​​적절히 캡슐화하고 코드를 단순화하며보다 명확하고 읽기 쉽도록 올바른 JDBC 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?