고성능 Oracle JDBC 프로그래밍
연결 및 명령문 풀링 기능을 이용하여 Oracle 기반의 JDBC 프로그램 성능을 개선하는 방법을 학습합니다.
연결 풀링 및 명령문 풀링과 같은 풀링 기능을 사용하면 데이터베이스 집약적인 애플리케이션의 성능을 크게 개선할 수 있습니다. 풀링 기능을 사용하지 않을 경우, 처음부터 객체를 새로 만들어야 하므로 시간과 리소스가 많이 소모되지만 풀링을 사용하면 객체를 다시 사용할 수 있기 때문입니다.
애플리케이션에서 사용한 물리적 데이터베이스 연결을 나타내는 데이터베이스 연결 객체를 다시 사용할 경우, 성능을 크게 개선시킬 수 있습니다. 단, 해당 애플리케이션은 동일한 매개 변수를 사용하여 연결을 수시로 재설정하면서 데이터베이스와 끊임없이 상호 작용해야 합니다. 반면, 애플리케이션이 기본 데이터베이스에 연결하는 경우가 거의 없다면 연결 풀을 사용하는 이점이 별로 없을 것입니다. 그러나 실제로는 허용되는 최대/최소 연결 수에 대한 한도 설정 같은 풀 설정이 특정 애플리케이션에 맞게 최적화되어 있다면 많은 데이터베이스 집약적인 애플리케이션이 연결 풀을 사용함으로써 이점을 누릴 수 있습니다.
연결 풀처럼 명령문 풀도 애플리케이션 성능을 개선할 수 있는 방법을 제공합니다. 프로그램을 실행하는 중에 여러 번 실행되는 명령문을 풀링함으로써 추가적인 성능 개선을 얻을 수 있습니다. 그러나 명령문 풀링이 성능 문제를 해결할 수 있는 특효약은 아니라는 점을 기억하십시오. 만약 프로그램에서 명령문이 실행되는 횟수를 구분하지 않고 모든 단일 명령문을 캐시 한다면 성능 개선을 이루지 못할 수 있습니다. 프로그램 실행 중에 한 번만 실행되는 명령문을 캐시할 경우, 해당 명령문을 캐시에 넣고 보관하는 작업과 관련된 오버헤드로 인해 실제로는 성능이 저하될 수 있습니다.
이 문서에서는 Oracle JDBC 씬 드라이버를 통해 Oracle Database와 상호 작용하는 데이터 집약적인 JDBC(Java DataBase Connectivity) 프로그램의 성능을 개선하기 위해 연결 및 명령문의 풀링을 이용하는 방법을 설명합니다. 특히 JDBC 연결을 캐시하기 위해 모든 기능을 갖춘 연결 풀 구현을 제공하는 JDBC용 Oracle Universal Connection Pool(UCP)을 살펴보겠습니다. 마지막으로 Oracle의 JDBC 드라이버뿐 아니라 명령문 인터페이스에 추가되고 JDK(Java Development Kit) 1.6 이상 버전을 지원하는 Oracle JDBC 드라이버에서 사용할 수 있는 새로운 JDBC 4.0 메소드에 관련된 기능을 사용함으로써 명령문 풀링에서 이점을 얻을 수 있는 방법을 설명하겠습니다.
작업 환경 설정
이 문서의 예제를 수행하려면 Oracle 데이터베이스에 대한 액세스 권한이 있어야 하며 더불어 다음과 같은 소프트웨어 구성 요소가 개발 시스템에 설치되어 있어야 합니다. (다음에 대한 링크는 "다운로드" 포틀릿 참조)
- JDK 1.6
- JDK 1.6을 지원하는 Oracle JDBC 씬 드라이버
- Oracle Universal Connection Pool 라이브러리
Oracle JDBC 씬 드라이버는 IV형 JDBC 드라이버입니다. 이는 이 드라이버가 플랫폼과는 상관이 없으며 Oracle Database와 상호 작용하기 위해 클라이언트 측에 추가 Oracle 소프트웨어가 필요하지 않음을 의미합니다. 따라서 JDBC 드라이버 다운로드 페이지에서 적절한 씬 드라이버 버전의 클래스가 포함된 JAR 파일을 다운로드한 다음, 다른 Oracle 소프트웨어를 설치/업그레이드하지 않고도 시스템에 드라이버를 설치할 수 있습니다. 드라이버를 설치하려면 JAR 파일을 로컬 파일 시스템에 복사한 다음 CLASSPATH 환경 변수에 이 JAR 경로를 포함시키기만 하면 됩니다. 예를 들어, 다음 경로를 포함시킬 수 있습니다.
Oracle 데이터베이스가 시스템에 설치되어 있는 경우, Oracle Database 설치와 함께 드라이버가 설치되어 있습니다. 그러나 씬 드라이버가 추가 Oracle 소프트웨어를 필요로 하지 않기 때문에 JDBC 드라이버 다운로드 페이지에 있는 적절한 JAR 파일을 사용하여 최신 버전의 드라이버로 쉽게 업그레이드할 수 있습니다.
UCP는 11.1.0.7 버전부터 Oracle Database 11g에 포함되어 있는 새로운 기능입니다. Oracle Application Server 11g 릴리스 1부터 Oracle Application Server에서도 이 기능을 사용할 수 있습니다. UCP용 JAR 파일(ucp.jar)을 제공하지 않는 이전 소프트웨어를 사용하고 있거나 최신 UCP 릴리스로 업그레이드하고자 하는 경우, Oracle Database UCP 다운로드 페이지에서 ucp.jar을 선택할 수 있습니다. 이 패키지에는 기능을 사용하기 위해 클래스 경로에 포함할 UCP의 클래스가 들어 있습니다. 포함된 경로는 다음과 같습니다.
UCP를 사용하여 JDBC 연결 캐시
데이터베이스 집약적인 애플리케이션을 개발할 경우, 연결 풀을 사용하여 이점을 누릴 수 있습니다. 연결 풀을 사용하면 연결을 요청할 때마다 새로 생성하는 대신 연결을 재사용할 수 있습니다. 연결 풀링을 사용하면 새로운 데이터베이스 연결을 생성하는 데 필요한 리소스를 절약하여 애플리케이션 성능을 개선할 수 있습니다. 연결을 새로 생성하는 작업은 언제나 성능 집약적인 작업이기 때문입니다.
JDBC용 Oracle Universal Connection Pool은 JDBC 연결을 캐시하는 연결 풀의 완벽한 기능의 구현을 대표합니다. UCP는 매우 유용한 기능으로써 연결 객체를 재사용하도록 하여 연결 프로세스를 빠르게 하고 새 데이터베이스 연결 열기와 관련된 리소스를 절약할 수 있습니다.
HR/HR Oracle Database 샘플 스키마에 설정된 연결을 다시 사용하기 위해 UCP JDBC 연결 풀을 생성하는 경우를 가정해봅니다. 간단한 UCP JDBC 연결 풀 예제를 나타내는 다음 프로그램에서 그 방법을 보여줍니다. 여기에서는 먼저 풀이 활성화된 데이터베이스 소스 인스턴스를 생성한 다음 연결 및 풀 속성을 설정합니다. 이 작업을 마치면 풀에서 연결을 가져온 다음 해당 연결을 사용하여 데이터베이스와 상호 작용합니다. 마지막으로 연결을 닫고 풀로 반환합니다.
여기서 중요한 점은 연결을 닫을 경우 어떤 일이 발생하는가 하는 점입니다. 위 프로그램의 결과에서는 UCP JDBC 연결 풀에서 가져온 연결을 닫을 경우 실제로 해당 연결이 풀로 반환되어 다음 연결 요청 시 사용할 수 있음을 보여줍니다.
다음은 프로그램의 결과입니다.
풀에서 가져온 연결
사용 가능한 연결: 4
가져온 연결: 1
연결 상태: HR
풀에 반환된 연결
사용 가능한 연결: 5
가져온 연결: 0
JNDI를 사용하여 연결 가져오기
쉴새 없이 풀이 활성화된 데이터 소스를 만드는 대신, 이전 예제에서 했던 것처럼 연결을 미리 생성하여 이 연결을 JNDI(Java Naming and Directory Interface) 컨텍스트와 논리 명에 바인딩할 수 있습니다. 데이터 소스를 JNDI에 등록한 경우, JNDI 조회를 수행하고 데이터 소스가 바인딩된 JNDI 이름을 지정하여 데이터 소스의 인스턴스를 가져올 수 있습니다.
HR/HR 데이터베이스 스키마에 대한 연결을 다시 사용하기 위해 설계된, 풀이 활성화된 데이터 소스를 JNDI 트리의 jdbc/HRPool 논리 명과 연결하여 이 데이터 소스를 등록하는 경우를 가정해보겠습니다. 이 작업을 수행하려면 위 데이터 소스를 나타내는 PoolDataSource 객체를 생성하여, 해당 속성을 설정한 다음, 이 객체를 JNDI 이름 서비스에 등록해야 합니다. 다음 Java 프로그램을 사용하여 이 작업을 수행할 수 있습니다.
이 프로그램을 실행하기 전에 다운로드할 수 있는 Sun의 파일 시스템 JNDI 서비스 공급자를 설정해야 합니다. 다음 JAR 파일을 클래스 경로에 추가해야 위 프로그램을 실행할 수 있습니다.
위 프로그램을 실행한 후, jdbc/HRPool 풀이 활성화된 데이터 소스를 Java 애플리케이션에서 사용할 수 있습니다. 이는 JavaServer 페이지, 서블릿 또는 독립형 애플리케이션일 수 있습니다. 다음은 이 데이터 소스를 사용하는 독립형 Java 애플리케이션입니다.
위 프로그램에서 첫 번째 할 일은 JNDI 컨텍스트를 초기화하는 것입니다. 이 JNDI 컨텍스트를 사용하여 jdbc/HROracle 풀이 활성화된 데이터 소스를 위해 JNDI 조회를 수행합니다. 그 다음 JNDI 조회에서 반환한 데이터 소스 인스턴스에서 연결을 가져와 이 연결을 사용하여 데이터베이스에 대한 쿼리를 실행합니다.
이미 알고 있는 것처럼 이 섹션에서 설명한 방법은 연결 풀을 사용하는 프로세스를 단순화시켜 줍니다. 풀이 활성화된 데이터 소스를 한 번 등록한 다음 필요할 때 JNDI 조회를 사용하여 해당 인스턴스를 가져오면 연결 풀을 초기화할 때마다 연결 풀 속성을 설정할 필요가 없습니다. 미리 정의된 속성을 가진 풀 인스턴스를 가져오면 됩니다.
고가용성 및 성능
풀 새로고침 및 연결확인 같은 새로운 JDBC 4.0 고가용성 및 성능 기능을 UCP에서 지원하고 있다는 사실을 강조하고자 합니다. 이 기능은 Oracle RAC(Real Application Clusters)와 관련이 없기 때문에 Oracle RAC 데이터베이스가 필요하지 않습니다.
그리고 UCP는 연결을 가져올 때 연결을 확인할 수 있는 기능을 제공합니다. 가져올 때 연결을 확인할 수 있는 기능을 사용하면 연결을 사용하기 전에 연결이 여전히 유효한지 확인할 수 있기 때문에 매우 유용합니다. 이 문제를 해결하기 위해 UCP JDBC 연결 풀 인스턴스에는 부울(Boolean) 형식의 ValidateConnectionOnBorrow 속성이 있습니다. setValidateConnectionOnBorrow 메소드를 사용하여 이 속성을 "true"로 설정해야 합니다.
그런 다음 연결이 여전히 유효한지 확인하기 위해 실행할 SQL 문을 지정해야 합니다. setSQLForValidateConnection 메소드를 사용하여 이 작업을 수행할 수 있습니다.
그러나 Oracle JDBC 드라이버를 사용할 경우, SQLForValidateConnection 속성을 설정할 필요가 없습니다. 풀에서 내부 핑(ping)을 수행하여 가져올 연결의 유효성을 테스트합니다.
가져올 때 연결을 확인하는 것은 바람직합니다. 그러나 가져올 때 성공적으로 확인한 후에 연결이 사용할 수 없게 된 경우 어떻게 해야 할까요? 연결을 가져온 다음 연결을 확인할 수 있는 다른 방법이 있습니까? 이 문제를 해결하기 위해 JDBC 4.0 사양에서는 isValid 메소드를 Connection 인터페이스에 추가하여 원할 때 연결의 유효성을 테스트할 수 있게 하고 있습니다.
한 단계 더 나아가 JDBC용 UCP에서는 다음 두 개 메소드가 포함된 oracle.ucp.jdbc.ValidConnection 인터페이스를 제공합니다. 바로 isValid 및 setInvalid 메소드입니다. 이 메소드는 재귀 또는 반복(루프)과 함께 구현된 재시도 메커니즘과 같이 사용할 경우 특히 유용합니다. 예를 들어, 연결을 사용할 수 없게 되어 작업을 수행할 수 없게 된 경우 연결을 반복 호출함으로써 연결을 가져온 다음 연결을 사용하는 메소드를 구현할 수 있습니다. 이러한 반복 메커니즘을 구현할 때 주의해야 할 점은 반복 호출 수를 제한할 수 있는 기능을 제공해야 한다는 점과 새로운 반복 호출을 할 때마다 해당 숫자를 줄여야 무한 루핑 가능성을 방지할 수 있다는 점입니다.
다음은 반복을 기반으로 한 새로운 재시도 메커니즘과 함께 oracle.ucp.jdbc.ValidConnection 인터페이스 메소드를 사용하는 방법을 보여주는 간단한 프로그램입니다.
이 예제에서 getUser 메소드는 동일한 메소드에 구현된 try/catch 문의 catch 절 내에서 자신을 호출합니다. 여기서 허용된 반복 호출 수는 3으로 제한합니다. 유효한 연결 가져오기가 연속적으로 세 번 실패할 경우 가져오기 시도를 중지하고 종료합니다.
위에서 설명한 일반적인 고가용성 및 성능 기능과는 별도로 JDBC용 UCP를 FCF(Fast Connection Failover) 및 런타임 연결 로드 밸런싱 같은 Oracle RAC 기능과 통합하여 Oracle RAC 데이터베이스 연결을 더 쉽게 관리할 수 있습니다.
다음 코드에서는 Oracle RAC 데이터베이스에 대한 연결을 관리하는 UCP JDBC 연결 풀을 사용할 경우 FCF를 활성화할 수 있는 방법을 보여줍니다. FCF를 사용하려면 Oracle Notification Service 라이브러리(ons.jar)를 애플리케이션의 클래스 경로에 추가해야 합니다. Oracle Database 10g부터 Oracle Notification Service 라이브러리가 Oracle Database의 일부로 제공됩니다.
연결 풀을 설정하고 FCF를 활성화한 경우, 풀에서 연결을 가져오고 RAC가 아닌 프로그램에서 하는 것처럼 연결에 대한 쿼리를 만들 수 있습니다.
그런 다음 RAC-down 이벤트가 UCP FCF 작업을 트리거한 후 연결의 유효성을 확인하는 재시도 메커니즘을 구현하여 연결을 사용할 수 없게 된 경우 남은 RAC 인스턴스에 다시 연결을 시도해볼 수 있습니다. 다음 코드에서는 while 루프 안에서 이 메커니즘을 구현하는 방법을 보여줍니다.
풀에서 연결을 성공적으로 가져오고 명령문 실행 시 예외가 트리거되지 않은 경우, 작업을 재시도할 필요가 없으므로 실행 흐름이 루프를 벗어나게 됩니다. 그렇지 않으면 다시 연결을 시도하고 명령문을 다시 실행합니다.
연결 풀 최적화
UCP JDBC 연결 풀은 풀링 동작을 최적화하기 위해 사용할 수 있는 속성 집합을 제공합니다. 예를 들어, 초기, 최대 및 최소 풀 사이즈를 제어하는 속성을 설정하여 풀 사이즈를 조정할 수 있습니다. 이전 섹션에서는 이 속성을 설정할 수 있는 방법을 배웠습니다.
풀 사이즈를 제어하는 속성과는 별도로 오래된 연결을 제어하는 속성도 있습니다. 예를 들어, 풀의 MaxConnectionReuseTime 속성을 설정하여 연결을 재사용할 수 있는 최대 시간을 구성할 수 있습니다. 일부 환경에서는 특정 횟수만큼 연결을 가져온 후에는 풀에서 연결을 제거하는 것이 유용한 경우가 있을 수도 있습니다. MaxConnectionReuseCount 속성을 설정하여 이 작업을 수행할 수 있습니다.
AbandonConnectionTimeout 속성을 설정하여 특정 기간 동안 연결을 사용하지 않을 경우 풀에서 가져온 연결을 회수하도록 지시할 수 있습니다. 또한 TimeToLiveConnectionTimeout 속성을 설정하여 풀에서 연결을 회수하기 전에 가져온 연결을 사용할 수 있는 기간을 제한할 수 있습니다.
만약 언젠가 풀에 연결이 없는 경우가 예상된다면 풀에서 사용할 수 있는 연결이 없는 경우에 애플리케이션 요청이 연결을 대기하는 시간(초)으로 ConnectionWaitTimeout 속성을 설정하도록 할 수 있습니다. 또한 연결을 풀에서 제거하기 전에 사용 가능한 연결을 가져오지 않은 상태로 유지할 수 있는 기간을 지정할 수 있는 InactiveConnectionTimeout 속성도 있습니다.
또 다른 흥미로운 속성으로는 TimeoutCheckInterval이 있습니다. 이 속성을 사용하면 위에서 설명한 timeout 속성을 실행하는 빈도를 제어하는 시간 초과 확인 간격을 설정할 수 있습니다. 기본적으로 이 속성은 30으로 설정되어 있습니다. 이는 30초마다 시간 초과 확인 주기가 실행된다는 것을 의미합니다.
이 섹션에서 지금까지 설명한 모든 최적화 기능을 사용하여 원하는 결과를 얻으려면 해당 속성을 적절한 값으로 설정해야 합니다. 그러나 풀에서 특정한 개수의 연결을 사용할 수 있도록 보장하기 위해 사용하는 연결 수집 기능을 사용하려면 약간 더 복잡한 메커니즘을 사용해야 합니다. 이 섹션의 나머지 부분에서 예를 통해 이 기능을 설명하겠습니다.
풀의 사이즈 속성을 다음과 같이 설정해보겠습니다.
initialPoolSize를 10으로 설정하면 연결 풀을 초기화할 경우 10개의 연결을 사용할 수 있습니다. 다음 코드를 사용하면 연결 수집 기능을 활성화하여 풀의 연결을 수집할 수 있습니다.
위에서 설정한 속성은 풀의 사용 가능한 연결 수가 5로 떨어질 경우 풀에서 가져온 연결 2개를 회수하도록 지시합니다. 이제 풀에서 가져온 5개의 연결을 보관하기 위해 사용할 수 있는 5개의 연결 객체 어레이를 만들어보겠습니다.
그러나 위 어레이를 연결로 채우기 전에 연결에 등록될 콜백 객체 어레이를 만들어야 합니다. 콜백 객체는 ConnectionHarvestingCallback 추상 인터페이스의 사용자 정의 구현의 인스턴스여야 합니다. 이 섹션의 후반부에서 간단한 구현을 보여드리겠습니다.
다음 코드를 사용하여 5개의 CustConnectionHarvestingCallback 객체 어레이를 만듭니다.
다음 루프에서는 풀에서 4개 연결을 가져오고 연결에 등록될 4개의 콜백 객체도 만듭니다.
다섯 번째 연결을 가져와서 수집을 트리거하기 전에 테스트를 위해 특정 연결에서 수집을 비활성화할 수 있습니다. 사용 가능한 연결 수가 5로 떨어질 경우 가져온 연결 2개를 풀로 반환하도록 지정한 것을 기억하실 겁니다. 기본적으로 연결 수집 기능은 처음 가져온 2개 연결을 수집합니다. 따라서 이 예제에서는 conn[0] 및 conn[1]을 수집합니다. 그러나 conn[0]을 nonharvestable로 설정하여 conn[1]과 conn[2]를 수집하도록 합니다.
이제 풀에서 다섯 번째 연결을 가져와서 수집을 트리거해 보겠습니다.
이 섹션의 앞 부분에서 설명한 시간 초과 확인 간격에서 이 간격이 기본적으로 30으로 설정되어 있다고 설명한 내용을 기억해보십시오. 이렇게 설정할 경우 이 예제에서는 수집이 즉시 트리거되지는 않지만 30초 간격 내에 트리거됨을 의미합니다.
계획한 대로 작동되는지 확인하기 위해 연결에서 어떤 연결이 닫히고 풀에 반환되었는지 확인해볼 수 있습니다.
위 코드에서는 conn[1] 및 conn[2] 연결은 닫히고 풀에 반환된 반면, 다른 3개 연결은 여전히 "빌려준" 상태를 나타내는 결과가 생성됩니다.
마지막으로 다음 코드에서는 cleanup 메소드가 수집 중인 연결을 닫도록 ConnectionHarvestingCallback 추상 인터페이스를 구현하는 방법을 보여줍니다.
위 코드는 ConnectionHarvestingCallback 추상 인터페이스 구현의 간단한 예입니다. 실제 애플리케이션에서는 더 복잡한 구현을 사용하고자 할 수 있습니다. 특히 cleanup 메소드에서는 더 복잡한 논리를 구현해야 할 수도 있습니다. 예를 들어, 수집 중인 연결과 관련된 트랜잭션을 해당 연결을 닫기 전에 롤백하는 경우가 있을 수 있습니다.
이 섹션에서 배운 대로 풀링 동작을 최적화하기 위해 사용할 수 있는 몇 가지 UCP JDBC 연결 풀 속성이 있습니다. 사용자 애플리케이션 요구 사항에 가장 잘 맞는 조합을 찾기 위해 풀 설정을 시험해보는 것도 좋습니다.
명령문 풀링
명령문 풀링을 권장하는 이유는 그야말로 명확하지만, 데이터 집약적인 애플리케이션에서 명령문 풀링의 중요성은 아무리 강조해도 지나치지 않습니다. Oracle JDBC 드라이버는 명시적/암시적 명령문 캐싱을 지원하기 때문에 준비된 명령문과 호출 가능한 명령문을 캐시할 수 있습니다. 암시적 캐싱을 사용할 경우, 캐시에 명령문을 보내거나 캐시에서 명령문을 받기 위해 특별한 작업을 수행할 필요가 없습니다. 준비된 명령문이나 호출 가능한 명령문 객체의 close 메소드를 호출할 경우, 해당 명령문이 자동으로 캐시로 이동하기 때문입니다. 다음에 이 동일한 연결에서 이 명령문을 생성할 경우, 처음부터 새로 명령문을 생성하는 대신 캐시에서 명령문을 검색합니다. 암시적 캐싱을 사용할 경우, 다음 조건이 충족되면 캐시에서 명령문 객체를 다시 사용합니다.
- 명령문에서 사용된 SQL 문자열에 캐시에 보관된 문자열과 같습니다.
- 명령문 유형(준비된 명령문 또는 호출 가능한 명령문)도 동일합니다.
- 명령문에서 생성한 결과 집합의 스크롤 가능 형식(정방향 전용 또는 스크롤 가능) 또한 동일합니다.
암시적 캐싱이 활성화되어 있다는 가정 하에 Oracle JDBC 드라이버가 설계되긴 했지만 이 기능이 기본적으로 활성화되어 있지는 않습니다. 연결에서 암시적 캐싱을 활성화하려면 해당 OracleConnection 객체의 implicitCachingEnabled 속성을 "true"로 설정하고 statementCacheSize 속성을 양의 정수로 설정합니다. 다음과 같이 할 수 있습니다.
UCP JDBC 연결 풀을 사용할 경우, maxStatements 속성을 양의 정수로 설정하여 명령문 캐싱을 활성화할 수 있습니다.
이 작업을 수행하면 풀의 연결마다 명령문 캐싱이 활성화됩니다. 다음 프로그램에서는 연결 풀링과 동시에 명령문 풀링을 사용하는 방법에 대한 간단한 예제를 제공합니다.
위에 표시된 클래스의 getRegion 메소드는 준비된 명령문을 생성하고, 실행한 후 닫고, 쿼리 결과를 호출한 코드에 반환합니다. 주 메소드에서 실행 중인 루프에서 이 메소드가 반복적으로 호출되므로 암시적 명령문 캐싱이 가능합니다. 이 예제에서는 연결 풀 인스턴스의 setMaxStatements 메소드를 호출할 때 암시적 캐싱을 활성화했습니다. 따라서 getRegion 메소드에서 준비된 명령문의 close 메소드를 호출할 경우, 실제로는 명령문을 닫는 대신 명령문을 캐시합니다. 따라서 프로그램은 getRegion에 대한 두 번째 이후의 호출에서 명령문을 다시 사용할 수 있습니다. 예상한 대로 작동하도록 다음 코드를 getRegion 메소드에 추가할 수 있습니다. OracleConnection 객체의 prepareStatement 메소드를 호출한 후 바로 다음 코드를 삽입합니다.
이제 프로그램을 실행하면 준비된 명령문의 생성 상태가 getRegion을 처음 호출한 경우에만 새로운 상태이고, 모든 후속 getRegion 호출에서는 암시적으로 캐시된 명령문을 다시 사용하는 것을 알 수 있습니다.
풀의 모든 연결에 있는 모든 명령문마다 명령문 캐싱을 활성화할 수 있게 하는 것은 시작에 불과합니다. 어떻게 이 기능을 선택적으로 적용하여 특정한 풀링 연결에서는 명령문 캐싱을 비활성화하거나, 특정 명령문에 대해서는 캐싱을 아예 비활성화할 수 있습니까?
이 섹션의 시작 부분에 있는 설명을 기억해보면 OracleConnection implicitCachingEnabled 속성을 사용하여 특정 연결에 대한 명령문 캐싱을 활성화하거나 비활성화할 수 있음을 알 수 있습니다. 예를 들어, 다음과 같이 풀의 연결마다 명령문 캐싱을 활성화한 다음, 특정 연결에서 명령문 캐싱을 비활성화할 수 있습니다.
특정 명령문에서 캐싱을 활성화/비활성화하는 경우, Statement 인터페이스에 추가된 새로운 JDBC 4.0 메소드를 이용할 수 있습니다. 특히 명령문 객체를 풀링 가능 또는 풀링 불가능하게 하려면 setPoolable 메소드를 각각 "true" 또는 "false"로 전달하여 설정할 수 있습니다. 명령문 객체의 현재 풀링 가능 상태를 확인하려면 해당 객체의 isPoolable 메소드를 사용합니다. 다음에서는 특정한 준비된 명령문이 암시적 캐시로 이동하지 못하도록 하는 방법을 보여줍니다.
여기서 흥미로운 점은 연결에서 암시적 캐싱이 활성화되지 않은 경우, setPoolable(true) 메소드를 사용하여 특정 명령문에 대해 암시적 캐싱을 활성화하려는 시도가 원하는 결과를 생성하지 못한다는 것입니다. 명령문 객체의 poolable 속성이 기본적으로 "true"로 설정되어 있더라도 이 섹션의 시작 부분에서 설명한 것처럼 먼저 해당 연결 또는 전체 연결 풀에 대한 암시적 캐싱을 활성화해야 합니다.
결론
이 문서에서는 뛰어난 Oracle 관련 JDBC 기능과 일반 JDBC 4.0 기능을 사용하여 연결 풀링 및 명령문 풀링을 이용하는 방법을 학습했습니다. 특히 JDBC 연결을 캐시하기 위한 연결 풀 구현을 제공하는 새로운 Oracle Database 11g 기능인 JDBC용 Oracle Universal Connection Pool에 대해 살펴보았습니다. 그리고 Oracle의 JDBC 드라이버에 관련된 기능과 Statement 인터페이스에 추가된 새로운 JDBC 4.0 메소드를 이용하여 명령문 풀링을 사용하는 방법에 대해 학습했습니다.
필자소개
Yuli Vasiliev 는 현재 오픈 소스 개발, Java 기술, 데이터베이스 및 SOA를 전문으로 하는 소프트웨어 개발자, 프리랜서 작가 겸 컨설턴트입니다. 그리고 "Beginning Database-Driven Application Development in Java EE: Using GlassFish (Apress, 2008)"의 저자이기도 합니다.