[java] Java에서 데이터베이스 연결 닫기

조금 혼란 스러워요. http://en.wikipedia.org/wiki/Java_Database_Connectivity 에서 아래를 읽고있었습니다 .

Connection conn = DriverManager.getConnection(
     "jdbc:somejdbcvendor:other data needed by some jdbc vendor",
     "myLogin",
     "myPassword" );

Statement stmt = conn.createStatement();
try {
    stmt.executeUpdate( "INSERT INTO MyTable( name ) VALUES ( 'my name' ) " );
} finally {
    //It's important to close the statement when you are done with it
    stmt.close();
}

conn 연결을 닫을 필요가 없습니까? conn.close ()가 발생하지 않으면 실제로 무슨 일이 일어나고 있습니까?

현재 두 양식 중 하나를 닫지 않는 비공개 웹 앱이 있지만 중요한 것은 실제로 stmt 하나, conn 하나 또는 둘 다입니까?

사이트가 간헐적으로 다운되지만 서버는 데이터베이스 연결 문제라고 계속해서 말하고 있습니다. 제 의심은 닫히지 않았다는 것입니다.하지만 어느 쪽을 닫아야할지 모르겠습니다.



답변

사용이 끝나면 연결이 유지하고있을 수있는 다른 데이터베이스 리소스 (커서, 핸들 등)를 해제하기 위해 메서드를 Connection호출하여 명시 적으로 닫아야합니다 close().

사실, 자바의 안전 패턴은 당신이 종료하는 것입니다 ResultSet, Statement그리고 ConnectionA의 (순서대로) finally처럼, 블록 당신이 그들과 함께 할 때 뭔가를 :

Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;

try {
    // Do stuff
    ...

} catch (SQLException ex) {
    // Exception handling stuff
    ...
} finally {
    if (rs != null) {
        try {
            rs.close();
        } catch (SQLException e) { /* ignored */}
    }
    if (ps != null) {
        try {
            ps.close();
        } catch (SQLException e) { /* ignored */}
    }
    if (conn != null) {
        try {
            conn.close();
        } catch (SQLException e) { /* ignored */}
    }
}

finally블록 약간 (널 검사를 피하기 위해)으로 개선 될 수있다 :

} finally {
    try { rs.close(); } catch (Exception e) { /* ignored */ }
    try { ps.close(); } catch (Exception e) { /* ignored */ }
    try { conn.close(); } catch (Exception e) { /* ignored */ }
}

그러나 여전히 이것은 매우 장황하므로 일반적으로 도우미 클래스를 사용하여 null-safe 도우미 메서드에서 개체를 닫고 finally블록은 다음과 같이됩니다.

} finally {
    DbUtils.closeQuietly(rs);
    DbUtils.closeQuietly(ps);
    DbUtils.closeQuietly(conn);
}

그리고 실제로 Apache Commons DbUtils 에는 DbUtils정확하게이를 수행 하는 클래스가 있으므로 직접 작성할 필요가 없습니다.


답변

사용 후에는 항상 데이터베이스 / 리소스 개체를 닫는 것이 좋습니다. finally블록 에서 연결, 결과 집합 및 문 개체를 닫는 것이 좋습니다.

Java7까지 이러한 모든 리소스는 finally블록을 사용하여 닫아야합니다 . Java 7을 사용하는 경우 리소스를 닫기 위해 다음과 같이 할 수 있습니다.

try(Connection con = getConnection(url, username, password, "org.postgresql.Driver");
    Statement stmt = con.createStatement();
    ResultSet rs = stmt.executeQuery(sql);
) {

//statements
}catch(....){}

이제 con, stmt 및 rs 객체는 try 블록의 일부가되고 java는 사용 후 이러한 리소스를 자동으로 닫습니다.

도움이 되었기를 바랍니다.


답변

그냥 닫습니다 충분 Statement하고 Connection. ResultSet개체 를 명시 적으로 닫을 필요가 없습니다 .

Java 문서는 다음에 대해 말합니다 java.sql.ResultSet.

ResultSet 개체는 해당 Statement 개체가 닫히거나 다시 실행될 때 생성 한 Statement 개체에 의해 자동으로 닫히거나 여러 결과 시퀀스에서 다음 결과를 검색하는 데 사용됩니다.


코멘트에 대해 BalusC에게 감사드립니다 : “나는 그것에 의존하지 않을 것입니다. 일부 JDBC 드라이버는 그것에 실패합니다.”


답변

예. 결과 집합, 문 및 연결을 닫아야합니다. 연결이 풀에서 제공된 경우 연결을 닫으면 실제로 다시 풀로 다시 보내 재사용됩니다.

일반적으로 finally{}블록 에서이 작업을 수행 해야하므로 예외가 발생하더라도이를 닫을 기회가 있습니다.

많은 프레임 워크가이 리소스 할당 / 할당 해제 문제를 처리합니다. 예 : Spring의 JdbcTemplate . Apache DbUtils 에는 null 여부에 관계없이 결과 집합 / 문 / 연결을 닫은 후 (그리고 닫을 때 예외를 포착하는) 방법이 있습니다.


답변

실제로 try-with-resources 블록을 사용하는 것이 가장 좋으며 try 블록을 종료하면 Java가 모든 연결을 자동으로 닫습니다.

AutoClosable을 구현하는 모든 개체로이 작업을 수행해야합니다.

try (Connection connection = getDatabaseConnection(); Statement statement = connection.createStatement()) {
    String sqlToExecute = "SELECT * FROM persons";
    try (ResultSet resultSet = statement.execute(sqlToExecute)) {
        if (resultSet.next()) {
            System.out.println(resultSet.getString("name");
        }
    }
} catch (SQLException e) {
    System.out.println("Failed to select persons.");
}

getDatabaseConnection에 대한 호출이 방금 구성되었습니다. JDBC SQL 연결 또는 풀에서 연결을 가져 오는 호출로 바꾸십시오.


답변

예, 연결을 종료해야합니다. 그렇지 않으면 데이터베이스 클라이언트는 일반적으로 소켓 연결 및 기타 리소스를 열어 둡니다.


답변