JDBC 결과 세트와 문은 나중에 닫히지만 별도로 닫아야 합니까?
사용 후에는 모든 JDBC 리소스를 닫는 것이 좋은 습관이라고 알려져 있습니다.단, 다음 코드가 있는 경우 결과 세트와 스테이트먼트를 닫을 필요가 있습니까?
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = // Retrieve connection
stmt = conn.prepareStatement(// Some SQL);
rs = stmt.executeQuery();
} catch(Exception e) {
// Error Handling
} finally {
try { if (rs != null) rs.close(); } catch (Exception e) {};
try { if (stmt != null) stmt.close(); } catch (Exception e) {};
try { if (conn != null) conn.close(); } catch (Exception e) {};
}
문제는 연결을 닫으면 작업이 수행되는지 아니면 일부 리소스를 계속 사용할 수 있는지 여부입니다.
당신이 한 일은 완벽하고 아주 좋은 연습입니다.
좋은 방법이라고 말하는 이유는...예를 들어 어떤 이유로 데이터베이스 풀링의 "primitive" 유형을 사용하고 있는 경우connection.close()
, 접속이 풀로 반환되어ResultSet
/Statement
절대 닫히지 않을 것이고 그러면 당신은 많은 다른 새로운 문제에 직면하게 될 것이다!
그래서 항상 믿을 수는 없다.connection.close()
청소하러 왔어요.
이것이 도움이 되었으면 합니다:)
Java 1.7은 리소스를 사용한 시도 문구를 통해 우리의 삶을 훨씬 더 쉽게 만듭니다.
try (Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement()) {
try (ResultSet resultSet = statement.executeQuery("some query")) {
// Do stuff with the result set.
}
try (ResultSet resultSet = statement.executeQuery("some query")) {
// Do more stuff with the second result set.
}
}
이 구문은 꽤 간결하고 우아하다.그리고.connection
심지어 ...이때도 확실히 닫힐 것이다.statement
생성할 수 없습니다.
javadocs에서:
어떤 경우
Statement
객체가 닫혀 있고, 객체의 전류ResultSet
오브젝트(존재하는 경우)도 닫힙니다.
단, 자바독은 다음 중 어느 쪽이 적절한지에 대해서는 그다지 명확하지 않습니다.Statement
그리고.ResultSet
기본을 닫으면 닫힙니다.Connection
. Connection을 닫는 것은 다음과 같습니다.
이 릴리스
Connection
오브젝트의 데이터베이스 및 JDBC 리소스가 자동으로 릴리스되기를 기다리지 않고 즉시 사용할 수 있습니다.
내 생각에, 항상 명백하게 가깝다고 생각한다.ResultSets
,Statements
그리고.Connections
실행으로서 그것들을 종료했을 때close
는 데이터베이스 드라이버에 따라 다를 수 있습니다.
다음과 같은 방법을 사용하면 보일러 플레이트 코드를 많이 절약할 수 있습니다.closeQuietly
DBUtils에 저장되어 있습니다.
현재 Oracle과 Java를 함께 사용하고 있습니다.제 견해는 다음과 같습니다.
닫아야 합니다.ResultSet
그리고.Statement
Oracle이 이전에 연결을 닫은 후에도 커서를 열어 두는 데 문제가 있었기 때문입니다.닫지 않으면ResultSet
(커서) Maximum open curs exceeded와 같은 오류가 발생합니다.
사용하고 있는 다른 데이터베이스에서도 같은 문제가 발생할 수 있다고 생각합니다.
완료되면 ResultSet 닫기
가까운.
ResultSet
작업을 마치자마자 이의를 제기하다ResultSet
Statement
가 ""를 .ResultSet
닫힐 때으로 오브젝트, 닫힐 때 오브젝트, 닫힘ResultSet
한으로 줍니다.이는 가비지 컬렉터가 메모리를 회수할 수 있도록 하기 위해서입니다.ResultSet
오브젝트는 쿼리에 따라 메모리를 많이 사용할 수 있습니다.
ResultSet.close();
좀 더 콤팩트한 코드를 원한다면 Apache Commons DbUtils를 사용하는 것이 좋습니다.이 경우:
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = // Retrieve connection
stmt = conn.prepareStatement(// Some SQL);
rs = stmt.executeQuery();
} catch(Exception e) {
// Error Handling
} finally {
DbUtils.closeQuietly(rs);
DbUtils.closeQuietly(stmt);
DbUtils.closeQuietly(conn);
}
아니요, 연결 이외에는 아무것도 닫지 않아도 됩니다.JDBC 사양에 따라 상위 개체를 닫으면 하위 개체가 자동으로 닫힙니다. ★★★Connection
★★★★★★★★★★★★★★★★★★★★★를 종료합니다.Statement
이 접속에 의해 작성되었습니다.의 ★★★를 닫습니다.Statement
를 닫습니다.ResultSet
에 Statement
.도도상상상상다다Connection
.풀 가능 연결도 풀로 돌아가기 전에 청소해야 합니다.
길.Connection
많은 문장을 만들고 닫는 것이 적절합니다.는 거의 요.ResultSet
좀 것 Statement
★★★★★★★★★★★★★★★★★」Connection
닫게 될 거야.
상관없다Connection
.풀 가능 연결도 풀로 돌아가기 전에 청소해야 합니다.
'클린'이란 보통 결과 세트를 닫고 보류 중인 트랜잭션을 롤백하는 것을 의미하지만 연결을 닫지는 않습니다.그렇지 않으면 풀링의 의미가 없어진다.
JDBC와 관련된 리소스를 닫는 올바르고 안전한 방법('JDBC 리소스를 올바르게 닫는 방법 - Every Time'에서 인용):
Connection connection = dataSource.getConnection();
try {
Statement statement = connection.createStatement();
try {
ResultSet resultSet = statement.executeQuery("some query");
try {
// Do stuff with the result set.
} finally {
resultSet.close();
}
} finally {
statement.close();
}
} finally {
connection.close();
}
재사용 가능한 One Liner를 만들기 위해 다음과 같은 Method를 작성했습니다.
public void oneMethodToCloseThemAll(ResultSet resultSet, Statement statement, Connection connection) {
if (resultSet != null) {
try {
if (!resultSet.isClosed()) {
resultSet.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
if (!statement.isClosed()) {
statement.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
if (!connection.isClosed()) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
DB 쿼리를 전송하는 모든 클래스에 상속되는 부모 클래스에서 이 코드를 사용합니다.결과 세트가 없어도 모든 쿼리에 Oneliner를 사용할 수 있습니다.메소드는 ResultSet, Statement, Connection을 올바른 순서로 닫습니다.이게 내 마지막 블록의 모습입니다.
finally {
oneMethodToCloseThemAll(resultSet, preStatement, sqlConnection);
}
일부 편의 기능:
public static void silentCloseResultSets(Statement st) {
try {
while (!(!st.getMoreResults() && (st.getUpdateCount() == -1))) {}
} catch (SQLException ignore) {}
}
public static void silentCloseResultSets(Statement ...statements) {
for (Statement st: statements) silentCloseResultSets(st);
}
Java 6 폼에서는 닫기 전에 닫혔는지 안 닫혔는지 체크하는 것이 좋다고 생각합니다(예를 들어 일부 연결 풀러가 다른 스레드 내의 연결을 제거하는 경우). 예를 들어 네트워크 문제 - 문과 결과 집합 상태가 닫힐 수 있습니다.(흔히 있는 일은 아니지만 Oracle과 DBCP에서 이 문제가 발생했습니다).이 패턴은 (이전 Java 구문에서) 다음과 같습니다.
try {
//...
return resp;
} finally {
if (rs != null && !rs.isClosed()) {
try {
rs.close();
} catch (Exception e2) {
log.warn("Cannot close resultset: " + e2.getMessage());
}
}
if (stmt != null && !stmt.isClosed()) {
try {
stmt.close();
} catch (Exception e2) {
log.warn("Cannot close statement " + e2.getMessage());
}
}
if (con != null && !conn.isClosed()) {
try {
con.close();
} catch (Exception e2) {
log.warn("Cannot close connection: " + e2.getMessage());
}
}
}
이론적으로 이것은 100% 완벽하지 않다. 왜냐하면 폐쇄 상태를 확인하는 것과 폐쇄 상태 자체 사이에 상태 변화를 위한 약간의 여지가 있기 때문이다.최악의 경우 긴 시간 내에 경고가 표시되지만 장기 실행 쿼리의 상태 변경 가능성보다 작습니다.이 패턴은 "평균" 부하(150명의 동시 사용자)를 가진 실가동 환경에서 사용되고 있으며, 문제가 없었습니다.따라서 이 경고 메시지는 표시되지 않습니다.
현재 JDBC에서는 결과 세트와 스테이트먼트가 AutoCloseable 인터페이스를 구현하고 있는 것으로 기억합니다.즉, 파괴되거나 범위를 벗어나면 자동으로 닫힙니다.
언급URL : https://stackoverflow.com/questions/4507440/must-jdbc-resultsets-and-statements-be-closed-separately-although-the-connection
'programing' 카테고리의 다른 글
각각 전에 VueRouter에서 약속된 getter 사용 (0) | 2022.07.28 |
---|---|
Vue 및 TypeScript 클래스 데코레이터 구문과 함께 외부에서 정의된 구성 요소 사용 (0) | 2022.07.28 |
Vuex 이거.$store는 함수가 아니라 이것입니다.$store.syslog가 실행됩니다. (0) | 2022.07.27 |
Vuex는 'createStore'라는 이름의 내보내기를 제공하지 않습니다. (0) | 2022.07.27 |
슈퍼클래스에서 서브클래스로의 명시적 캐스팅 (0) | 2022.07.27 |