풀에서 JDBC 연결 닫기


109

JDBC 사용을위한 표준 코드 섹션은 다음과 같습니다.

Connection conn = getConnection(...);
Statement  stmt = conn.conn.createStatement (ResultSet.TYPE_SCROLL_INSENSITIVE,
                                                ResultSet.CONCUR_READ_ONLY);
ResultSet  rset = stmt.executeQuery (sqlQuery);

// do stuff with rset

rset.close(); stmt.close(); conn.close();

질문 1 : Connection Pool을 사용할 때 마지막에 Connection을 닫아야합니까? 그렇다면 풀링의 목적이 상실되지 않습니까? 그렇지 않은 경우 DataSource는 Connection의 특정 인스턴스가 해제되고 재사용 될 수있는시기를 어떻게 알 수 있습니까? 나는 이것에 대해 약간 혼란 스럽습니다.

질문 2 : 다음 방법이 표준에 가깝습니까? 풀에서 연결을 얻으려는 시도처럼 보이며 DataSource를 설정할 수없는 경우 구식 DriverManager를 사용하십시오. 런타임에 어떤 부분이 실행되고 있는지조차 확실하지 않습니다. 위의 질문을 반복하면 그러한 방법에서 나오는 연결을 닫아야합니까?

고마워요-MS.

synchronized public Connection getConnection (boolean pooledConnection)
                                                        throws SQLException {
        if (pooledConnection) {
                if (ds == null) {
                        try {
                                Context envCtx = (Context)
                                        new InitialContext().lookup("java:comp/env");
                                ds = (DataSource) envCtx.lookup("jdbc/NamedInTomcat");
                                return ds.getConnection();
                        } catch (NamingException e) {
                                e.printStackTrace();
                }}
                return (ds == null) ? getConnection (false) : ds.getConnection();
        }
        return DriverManager.getConnection(
                "jdbc:mysql://"+ipaddy+":"+dbPort +"/" + dbName, uName, pWord);
}

편집 : 스택 추적이 보이지 않기 때문에 풀링 된 연결을 얻고 있다고 생각합니다.

답변:


121

Connection Pool을 사용할 때 마지막에 Connection을 닫아야합니까? 그렇다면 풀링의 목적이 상실되지 않습니까? 그렇지 않은 경우 DataSource는 Connection의 특정 인스턴스가 해제되고 재사용 될 수있는시기를 어떻게 알 수 있습니까? 나는 이것에 대해 약간 혼란 스럽습니다.

예, 물론 풀링 된 연결도 닫아야합니다. 실제로 실제 연결을 둘러싼 래퍼입니다. 커버 아래에서 풀에 대한 실제 연결을 해제합니다. 실제 연결이 실제로 닫히거나 새 getConnection()호출에 재사용 되는지 여부를 결정하는 것은 풀에 달려 있습니다 . 따라서 연결 풀을 사용하는지 여부에 관계없이 모든 JDBC 리소스를 획득 한 블록 의 블록 에서 항상 역순으로 닫아야 합니다. Java 7에서는 문 을 사용하여 더 단순화 할 수 있습니다 .finallytrytry-with-resources


다음 방법이 표준에 가깝습니까? 풀에서 연결을 얻으려는 시도처럼 보이며 DataSource를 설정할 수없는 경우 구식 DriverManager를 사용하십시오. 런타임에 어떤 부분이 실행되고 있는지조차 확실하지 않습니다. 위의 질문을 반복하면 그러한 방법에서 나오는 연결을 닫아야합니까?

예는 꽤 무섭습니다. DataSource응용 프로그램 전체 DB 구성 클래스의 일부 생성자 / 초기화에서 응용 프로그램을 시작하는 동안 한 번만 조회 / 초기화하면 됩니다. 그런 다음 getConnection()나머지 애플리케이션 수명 동안 하나의 동일한 데이터 소스를 호출 하면됩니다. 동기화 나 null 검사가 필요하지 않습니다.

또한보십시오:


그것이하고있는 일입니다 (한 번 초기화), 그렇지 않습니까? ds는 인스턴스 변수이고 if (ds == null) ...은 초기화 부분입니다.
Manidip Sengupta

get-method에서 매번 확인 하는 getConnection()것은 이상합니다. 동기화 / 널 검사없이 동일한 클래스의 c'tor 또는 초기화 블록에서 수행하십시오. 한 번만 호출됩니다. 더 많은 힌트와 시작 예제를 보려면 이 문서가 유용 할 수 있습니다 .
BalusC

훌륭한 기사, BalusC. 내가 다루는 클래스는 DTO를 사용하여 데이터 계층을 구현합니다. 동의합니다. 초기화는 생성자에 있어야합니다. 이제이 클래스에는 conn, stmt 및 rset이 지역 변수로 각각 포함 된 수많은 메서드가 있으며 연결은 try 블록에 있으며 마지막으로 csrClose (conn, stmt, rset)를 한 줄로 호출합니다. 닫혀 있습니다 (역순). 이제 예제에서 개발 한 DTO는 DB 테이블 행의 미러 이미지입니다. 조인 (및 기타 절)이있는 복잡한 SQL 쿼리가 있습니다. 이러한 결과를 위해 DAO를 개발하는 방법에 대한 기사가 있습니까?
Manidip Sengupta

2
@yat : close()그것들 을 획득 / 생성 한 곳 finally과 매우 동일한 try블록 의 블록 에서 모두 호출해야 합니다. 이는 풀링 된 연결인지 여부와는 완전히 관계가 없습니다.
BalusC 2013 년

1
@iJava : 그 풀은 그가 무엇을하고 있는지 전혀 모르는 아마추어에 의해 작성되었습니다. 그것을 무시하고 실제 도서관으로 가십시오. 예 : HikariCP.
BalusC 2015 년

22

풀은 일반적으로 래핑 된 Connection 객체를 반환합니다. 여기서 close () 메서드는 재정의되어 일반적으로 풀에 대한 Connection을 반환합니다. close () 호출은 괜찮으며 여전히 필요합니다.

close () 메서드는 다음과 같습니다.

public void close() throws SQLException {
  pool.returnConnection(this);
}

두 번째 질문에 대해 로거를 추가하여 하단 블록이 실행되는지 여부를 표시 할 수 있습니다. 나는 당신이 데이터베이스 연결의 구성에 대해 한 가지 방법만을 원한다고 상상할 것입니다. 우리는 데이터베이스 액세스를 위해서만 풀을 사용합니다. 어느 쪽이든 연결을 닫는 것은 누출을 방지하는 데 매우 중요합니다.


동의합니다. 로거가 있으며 여기에서도 사용할 수 있습니다. 난 당신이, 개체 포장의 close () 메소드를 오버라이드 (override)하지만 여전히 같은 클래스 이름을 유지할 수있는 방법에 대한 비트 (연결) 연구 할 필요가
Manidip Sengupta

1
Calling close() is OK and probably still required.풀 구현 일부 복구 전략 않는 한, 연결을 누출 가까운 호출하지
svarog

0

실제로 연결 관리에 대한 가장 좋은 접근 방식은 아무 코드에도 연결하지 않는 것입니다.

연결을 열고 닫는 유일한 위치 인 SQLExecutor 클래스를 만듭니다.

그런 다음 애플리케이션의 전체 나머지 부분은 풀에서 연결을 가져 와서 모든 곳에서 관리 (또는 잘못 관리)하는 대신 명령문을 실행기로 펌프합니다.

원하는만큼 실행기의 인스턴스를 가질 수 있지만, 아무도 스스로 연결을 열고 닫는 코드를 작성해서는 안됩니다.

편리하게도 단일 코드 세트에서 모든 SQL을 기록 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.