- xrath.com 에서 번역됨

[목차] [전의 항목] [다음의 항목]

## Connection

주: 이 장의 내용은, Addison Wesley 사부터 Java 시리즈의 1 권으로서 출판된 「JDBCTM API Tutorial and Reference, Second Edition:Universal Data Access for the JavaTM 2 Platform」(ISBN 0-201-43328-1)에 근거해 작성한 것입니다.

### 2.1 Connection 의 개요

`Connection` 객체는, 데이타베이스와의 접속을 나타냅니다. 접속 세션에는, 실행된 SQL 문과 그 접속을 개입시켜 반환된 결과가 들어갑니다. 1 개의 어플리케이션이 1 개의 데이타베이스와의 1 개 이상의 접속을 가지는 일도, 많은 다른 데이타베이스와의 접속을 가질 수도 있습니다.

`Connection.getMetaData` 메소드를 호출하면(자),`Connection` 객체의 데이타베이스의 정보를 취득할 수 있습니다. 이 메소드는, 데이타베이스의 테이블, 지원하고 있는 SQL 문법, 스트아드프로시쟈, 이 접속의 기능등의 정보가 포함되어 있는 `DatabaseMetaData` 객체를 돌려줍니다.

#### 2.1. 1 접속의 개시

데이타베이스와의 접속을 확립하는 종래의 방법은, 메소드 `DriverManager.getConnection` 를 호출하는 것입니다. 이 메소드는, URL 가 들어간 캐릭터 라인을 파라미터로서 받습니다. JDBC 관리 층으로 불리는 `DriverManager` 클래스는, URL 가 나타내는 데이타베이스에 접속할 수 있는 드라이버의 검색을 시도합니다. DriverManager 클래스는 등록을 마친 `Driver` 클래스의 리스트를 가져, 메소드 `getConnection` 가 불려 가면(자), URL 로 지정된 데이타베이스에 접속할 수 있는 드라이버가 발견될 때까지, 리스트안의 각 드라이버를 확인합니다. `Driver` 의 메소드의 `connect` 는, 이 URL 를 사용해 실제로 접속을 확립합니다.

사용자는, JDBC 관리 층을 우회도로 해,`Driver` 메소드를 직접 호출할 수가 있습니다. 이것은, 2 개의 드라이버가 데이타베이스에 접속할 수 있어 사용자가 특정의 드라이버를 명시적으로 선택한다고 하는 보기 드문 케이스에서는 도움이 됩니다. 그러나, 일반적으로은,`DriverManager` 클래스에 접속의 개시를 처리시키는 (분)편이 훨씬 간단합니다.

이하의 코드는,`oboy` 라고 하는 ID 와 `12Java` 라고 하는 패스워드를 사용해 URL `jdbc:odbc:wombat` 에 있는 데이타베이스에의 접속을 개시하는 예를 나타냅니다.

>     String url = "jdbc:odbc:wombat";
>     Connection con = DriverManager.getConnection(url, "oboy", "12Java");

JDBC 2.0 표준 확장 기능 API 에서는, 접속을 확립하기 위해서,`DriverManager` 의 대체로서 `DataSource` 인터페이스가 제공되고 있습니다. `DataSource` 클래스가 적절히 구현되고 있는 경우는,`DataSource` 객체를 사용해, 접속 풀에 관계하는 `Connection` 객체 또는 분산 트랜잭션(transaction)에 관계하는 `Connection` 객체, 혹은 그 양쪽 모두를 작성할 수 있습니다. 상세 및 `DataSource` 객체를 사용해 접속을 작성하는 코드예에 대해서는, 「DataSource」의 장을 참조해 주세요. 이 장에서는, 접속을 작성하는데,`DataSource` 객체의 사용이 좋은 대체 방법이 되는 이유에 대해서도 설명합니다.

어플리케이션에서는,`DataSource` 객체에 의해 생성된 `Connection` 객체는, 기본적으로 `DriverManager` 에 의해 생성된 `Connection` 객체와 같은 방법으로 사용됩니다. 다만, 몇개인가 차이점이 있습니다. `Connection` 객체가 풀 된 접속의 경우는, 어플리케이션에 `finally` 블록을 짜넣어, 예외가 throw 되었을 때에도 접속이 닫도록(듯이) 할 필요가 있습니다. 이 결과, 접속이 유효한 경우는, 항상 유효한 접속 풀로 돌아갑니다.

`Connection` 객체가 분산 트랜잭션(transaction)의 일부인 경우는, 어플리케이션으로부터 `Connection.commit` 메소드 또는 `Connection.rollback` 메소드를 호출하거나 접속의 자동 위탁 모드를 온으로 설정하거나 하지 말아 주세요. 트랜잭션(transaction) 매니저의 분산 트랜잭션(transaction) 처리를 방해할 가능성이 있습니다.

#### 2.1. 2 URL 의 일반적인 사용법

어플리케이션으로부터 `DriverManager` 를 사용해 `Connection` 객체를 생성할 때는, URL 를 `DriverManager.getConnection` 메소드에 건네줄 필요가 있습니다. URL 에 관해서는 혼란이 생기는 일이 자주 있으므로, 우선 URL 의 일반적인 설명을 간략한가에 행하고 나서, JDBC 의 URL 에 대해 설명하기로 하겠습니다.

URL (Uniform Resource Locator)는, 인터넷상의 자원의 위치를 지정하기 위해서 사용합니다. 이것은 주소라고 생각할 수가 있습니다.

URL 의 최초의 부분에서, 정보에 액세스 하기 위해서 사용하는 프로토콜을 지정합니다. 그 후에는 항상, 구두점이 계속됩니다. 자주(잘) 사용되는 프로토콜에는, 파일 전송 프로토콜을 지정하는 `ftp` 와 하이퍼 텍스트(hyper text) 전송 프로토콜을 지정하는 `http` 가 있습니다. 프로토콜이 `file` 의 경우는, 자원은 인터넷상은 아니고 로컬 파일 시스템에 포함되고 있는 것을 나타냅니다.

>           ftp://javasoft.com/docs/JDK-1_apidocs.zip
>           http://java.sun.com/products/JDK/CurrentRelease
>           file:/home/haroldw/docs/tutorial.html

URL 의 최초의 구두점의 후에 계속되는 나머지의 부분은 모두, 데이터 소스가 어디에 있는지를 지정하는 것입니다. 프로토콜이 `file` 의 경우에는, URL 의 나머지의 부분은 파일에 대한 패스가 됩니다. 프로토콜이 `ftp` 와 `http` 의 경우에는, URL 의 나머지의 부분은 호스트를 지정해서 , 보다 구체적인 사이트에 대한 패스를 옵션으로서 지정할 수도 있습니다. 예를 들어, 다음은, Java Software 의 홈 페이지에 대한 URL 가 됩니다. 이 URL 는 호스트만을 지정합니다.

>     http://www.java.sun.com

이 홈 페이지로부터, 다수외의 홈 페이지에 갈 수가 있습니다. JDBC 홈 페이지도 그 1 개(살)입니다. JDBC 홈 페이지의 URL 는 보다 구체적이어, 다음과 같이 되어 있습니다.

>     http://www.java.sun.com/products/jdbc

#### 2.1. 3 JDBC 의 URL

JDBC 의 URL 는, 적절한 드라이버가 데이터 소스를 인식해 그것과의 접속을 확립하도록(듯이), 데이터 소스를 식별하는 방법을 제공합니다. 드라이버의 작성자가, 특정의 드라이버를 식별하는 JDBC URL 를 무엇으로 할까를 실제로 결정합니다. 사용자는, JDBC URL 를 어떠한 형식 할까에 대해서는 걱정할 필요는 없습니다. 사용자는, 그 사용하고 있는 드라이버가 공급하는 URL 를 단지 사용할 뿐입니다 봅니다. JDBC 의 역할은, 단지 드라이버의 작성자가 JDBC 의 URL 를 구성할 때에 사용하는 규칙을 추천 할 뿐입니다.

JDBC 의 URL 는, 다양한 종류의 드라이버로 사용하기 위해(때문에), 규칙은 당연, 매우 유연합니다. 우선, 이 규칙에서는, 다른 드라이버가 데이타베이스를 이름 붙이기 위한 다른 구조를 사용할 수 있습니다. 예를 들어,`odbc` 서브 프로토콜을 사용하면(자), URL 에 속성치를 포함할 수가 있습니다 (다만, 필요로 하는 것은 아니다).

제 2 에, JDBC 의 URL 에 의해, 드라이버의 작성자가 필요한 접속 정보를 그 중에 encode 할 수 있게 됩니다. 이것에 의해, 예를 들어, 애플릿이 데이타베이스와 교환을 실시하려고 할 때, 사용자가 아무런 관리 작업을 실시하는 일 없이 데이타베이스 접속을 개시할 수가 있습니다.

제 3 에, JDBC 의 URL 에서는 간접적인 레벨이 가능합니다. 즉, JDBC 의 URL 가, 논리 호스트 또는 네트워크 네이밍 시스템에 의해, 실제의 이름에 동적으로 번역되는 데이타베이스명을 참조할 수 있다고 하는 것입니다. 이것에 의해, 시스템 관리 책임자는 특정의 호스트를 JDBC 명의 일부로서 지정하지 않아도 됩니다. 네트워크 네임 서비스에는 몇개의 다른 종류 (예를 들어, DNS, NIS, 및 DCE)가 있어, 어떤 것을 사용할까에 대한 제약은 없습니다.

JDBC URL 의 표준 구문은 다음과 같습니다. 그 구문에는 3 개의 부분이 있어, 구두점에 의해 단락지어지고 있습니다.

>     	jdbc:<subprotocol>:<subname>

JDBC 의 URL 의 3 개의 부분은 이하와 같이 분할할 수 있습니다.

1. `jdbc` 는 프로토콜입니다. JDBC 의 URL 의 프로토콜은 항상 `jdbc` 입니다.

2. `<subprotocol>` 는 일반적으로, 드라이버명 또는 데이타베이스 접속 메카니즘의 이름으로, 1 개(살) 이상의 드라이버에 의해 지원할 수가 있습니다. 서브 프로토콜명의 현저한 예는,`odbc` 로, 이것은 OBDC 스타일 데이터 소스명을 지정하는 URL 를 위해서(때문에) 예약되고 있습니다. 예를 들어, JDBC-ODBC 브릿지에 의해 데이타베이스에 액세스 하려면 , 이하와 같이 URL 를 사용합니다.

   >     	jdbc:odbc:fred

   이 예에서는, 서브 프로토콜은 `odbc` 로, 서브 네임은 로컬의 ODBC 데이터 소스명 `fred` 입니다.

   네트워크 네임 서비스를 사용하고 싶은 (JDBC 의 URL 중의 데이타베이스의 이름을 실제의 이름으로 할 필요를 없애고 싶다) 경우에는, 네임 서비스는 서브 프로토콜로 할 수 있습니다. 즉, 예를 들어, 다음과 같은 URL 를 가지고 있는 것으로 합니다.

   >     	jdbc:dcenaming:accounts-payable

   이 URL 는, 「로컬의 DCE 네임 서비스를 사용해 데이타베이스명 `accounts-payable` 를 해석해, 실제의 데이타베이스에의 접속에 사용할 수 있는 특정의 이름으로 변환한다」일을 지정하고 있습니다.

3. `<subname>` 는, 데이터 소스를 식별하는 방법입니다. 서브 네임은, 서브 프로토콜에 의해 여러가지로 변화할 수가 있어 드라이버의 작성자가 선택하는, 서브 서브 네임을 포함한 어떠한 내부 구문에서도 가질 수가 있습니다. 서브 네임의 포인트는, 데이터 소스를 찾기 위해서(때문에) 충분한 정보를 제공하는 것입니다. 상기의 예에서는, ODBC 가 나머지의 정보를 제공하므로,`fred` 로 충분합니다. 그러나, 원격 서버-위의 데이터 소스에서는, 좀 더 많은 정보가 요구됩니다. 예를 들어, 데이터 소스가 인터넷 경유로 액세스 되는 경우는, 네트워크 주소가 서브 네임의 일부로서 JDBC 의 URL 에 포함되어야 하는 것이어, 다음의 표준의 URL 명명 규칙에 따를 필요가 있습니다.

   >      	//hostname:port/subsubname

   `dbnet` 가 인터넷상의 호스트에게 접속하기 위한 프로토콜이라고 하면(자),JDBC 의 URL 는 이하와 같은 형태가 됩니다.

   >     	jdbc:dbnet://wombat:356/fred

#### 2.1. 4 "odbc" 의 서브 프로토콜

서브 프로토콜 `odbc` 는, 특별한 케이스입니다. 이것은 ODBC 스타일의 데이터 소스명을 지정하는 URL 를 위해서(때문에) 예약되어 서브 네임 (데이터 소스명)의 후에 임의의 수의 속성치를 지정할 수 있도록(듯이) 하는 특별한 기능을 갖추고 있습니다. odbc 서브 프로토콜의 완전한 구문은 이하대로입니다.

>       jdbc:odbc:<data-source-name>[;<attribute-name>=<attribute-value>]*

따라서, 이하는 모두 유효한 jdbc:odbc 명입니다.

>          jdbc:odbc:qeor7
>          jdbc:odbc:wombat
>          jdbc:odbc:wombat;CacheSize=20;ExtensionCase=LOWER
>          jdbc:odbc:qeora;UID=kgh;PWD=fooey

#### 2.1. 5 서브 프로토콜의 등록

드라이버 개발자는, JDBC 의 URL 로 서브 프로토콜로서 사용하는 이름을 예약할 수가 있습니다. `DriverManager` 클래스가 이 이름을 그 등록이 끝난 드라이버의 리스트에 나타내면(자), 이 이름으로 예약된 드라이버가 그것을 인식해, 거기에 따라 식별되는 데이타베이스에의 접속을 확립합니다. 예를 들어, 「odbc」는 JDBC-ODBC 브릿지를 위해서(때문에) 예약되고 있습니다. 또, 만일 Miracle Corporation 라고 하는 기업이 존재하면, 그 Miracle DBMS 에 접속하는 JDBC 드라이버의 서브 프로토콜로서 「miracle」를 등록해, 그 밖에 아무도 그 이름을 사용할 수 없게 합니다.

Java Software 는 JDBC 서브 프로토콜명의 비공식인 등록기관으로서 활동하고 있습니다. 서브 프로토콜명을 등록하려면 , 이하의 주소에 전자 메일을 보냅니다.

>     	jdbc@eng.sun.com

#### 2.1. 6 SQL 문의 송부

일단 확립되면(자), 접속은, SQL 문을 그 기반이 되는 데이타베이스에 건네주기 위해서(때문에) 사용됩니다. JDBC API 는 송부되는 SQL 문의 종류에 대해 어떤 제약도 부과하지 않기 때문에, 큰 유연성이 있어, 데이타베이스 고유의 문장이나 SQL 가 아닌 문장조차도 사용할 수가 있습니다. 다만 사용자는, 기반이 되는 데이타베이스가 송부되는 SQL 문을 처리할 수 있는 것을 확인할 책임이 있어, 처리할 수 없는 경우는 그 결과를 감수 할 필요가 있습니다. 예를 들어, 어플리케이션이, 스트아드프로시쟈를 지원하지 않는 DBMS 에 스트아드프로시쟈 호출을 송신하려고 하면(자), 정상적으로는 처리되지 않고, 예외 처리를 생성합니다.

JDBC API 는, SQL 문을 데이타베이스에 송부하기 위해서, 이하의 3 개의 인터페이스를 준비하고 있어,`Connection` 인터페이스의 대응하는 메소드는 그 인스턴스를 생성합니다. SQL 문 및 그것을 작성하는 `Connection` 메소드를 송신하는 인터페이스는, 다음과 같습니다.

1. `Statement` - `Connection.createStatement` 메소드에 의해 생성됩니다. `Statement` 객체는, 파라미터를 지정하지 않고 SQL 문을 송신할 경우에 사용합니다.
2. `PreparedStatement` - `Connection.prepareStatement` 메소드에 의해 생성됩니다. `PreparedStatement` 객체는, 프리컴파일 된 SQL 문에 사용합니다. SQL 문에는, 1 개(살) 이상의 파라미터를 입력 인수 (IN 파라미터)로서 지정할 수 있습니다. `PreparedStatement` 는 IN 파라미터의 값을 설정하는 메소드의 그룹을 가져, 이러한 IN 파라미터는 문장이 실행될 때 데이타베이스에 송부됩니다. `PreparedStatement` 의 인스턴스는,`Statement` 를 상속하고 있기 (위해)때문에 `Statement` 메소드를 포함합니다. `PreparedStatement` 객체는 컴파일이 끝난 상태로, 장래의 사용에 대비해 포함되고 있으므로,`Statement` 객체보다 효율적으로 사용할 수 있는 능력을 잠재적으로 갖추고 있습니다. 이 때문에,`PreparedStatement` 객체는, 퍼포먼스의 향상이 필요한 때에, 빈번하게 실행되는 SQL 문에 대해서 사용합니다.
3. `CallableStatement` - `Connection.prepareCall` 메소드에 의해 생성됩니다. `CallableStatement` 객체는, SQL 스트아드프로시쟈 (일련의 SQL 문으로, 함수를 기동하는 것 멈춘 구 같이 이름에 의해 불려 갑니다)를 실행하기 위해서 사용합니다. `CallableStatement` 객체는, IN 파라미터를 처리하기 위한 메소드를 `PreparedStatement` 로부터 상속해, 게다가 OUT 및 INOUT 파라미터를 처리하기 위한 메소드가 추가되고 있습니다.

   이하의 리스트는, 다른 타입의 SQL 문을 작성하기 위해서, 어느 쪽의 `Connection` 메소드가 적절한가를 재빠르게 판정하는 방법을 나타냅니다.

- `createStatement` 메소드 - 간단한 SQL 문 (파라미터 없음)에 대해서 사용된다
- `prepareStatement` 메소드 - 빈번하게 실행되는 SQL 문에 대해서 사용된다

- `prepareCall` 메소드 - 스트아드프로시쟈의 호출에 대해서 사용된다

이러한 메소드에서는, 인수를 지정하지 않기 때문에, 디폴트의 `ResultSet` 객체를 생성하는 문장이 작성됩니다. 즉, 스크롤 및 갱신을 실시할 수가 없는 결과 세트가 생성됩니다. JDBC 2.0 API 를 사용하면(자), 스크롤 또는 갱신, 혹은 그 양쪽 모두를 실시할 수가 있는 결과 세트가 생성되는 문장을 작성할 수 있습니다. 작성하려면 , 새로운 `createStatement`,`prepareStatement`, 및 `prepareCall` 메소드를 사용합니다. 이러한 메소드에는, 결과 세트의 형태 및 작성중의 결과 세트의 동시성 처리의 레벨을 지정하기 위해서, 추가의 파라미터를 지정할 수 있습니다. `ResultSet` 객체의 형태 및 형태를 지정하기 위한 정수에 대해서는,제 5 장 「ResultSet」의 「결과 세트의 형태」를 참조해 주세요. 동시성 처리의 레벨에 대해서는,「동시성 처리의 타입」 을 참조해 주세요. 문장을 작성할 경우에 새로운 `Connection` 메소드를 사용해 `ResultSet` 객체를 생성하는 방법에 대해서는,「타입이 다른 결과 세트의 작성」 을 참조해 주세요.

#### 2.1. 7 트랜잭션(transaction)

트랜잭션(transaction)는, 실행되어 완료되어 그 후에 위탁 혹은 롤백(rollback) 하는 1 개(살) 이상의 문장으로 구성됩니다. 메소드 `commit` 또는 `rollback` 가 불려 간 시점에서, 현재의 트랜잭션(transaction)가 종료해, 다른 트랜잭션(transaction)가 개시합니다.

일반적으로 디폴트에서는, 새로운 `Connection` 객체는 자동 위탁 모드가 되어 있습니다. 즉, 문장이 완료하면(자), 메소드 `commit` 가 자동적으로 그 문장으로 불려 갑니다. 이 경우, 각 문이 개개에 위탁되므로, 1 개의 트랜잭션(transaction)가 다만 1 개의 문장에 의해 구성되어 있습니다. 오토 위탁 모드가 무효가 되어 있으면(자), 트랜잭션(transaction)는 메소드 `commit` 또는 `rollback` 의 어느 쪽인지가 명시적으로 불려 갈 때까지 종료하지 않기 때문에,`commit` 또는 `rollback` 가 마지막에 기동된 이후의 실행된 모든 문장을 포함합니다. 이 2 번째의 경우, 트랜잭션(transaction)의 모든 문장은 그룹으로서 위탁 또는 롤백(rollback) 됩니다.

트랜잭션(transaction)를 개시할 경우에, 명시적인 호출은 필요 없습니다. 자동 위탁 모드를 무효로 했을 때, 또는 `commit` 또는 `rollback` 메소드를 호출한 후에, 암묵에 개시됩니다. 메소드 `commit` 는, SQL 문이 데이타베이스에 대해서 더한 모든 변경을 영속화해, 트랜잭션(transaction)에 의해 걸칠 수 있었던 락을 모두 해제합니다. 메소드 `rollback` 는 그러한 변경을 파기합니다.

다른 변경이와 같이 행해지지 않는 이상 있는 변경을 유효하게 하고 싶지 않은 경우가 있습니다. 이것은, 오토 위탁을 무효로 해, 양쪽 모두의 갱신 내용을 1 개의 트랜잭션(transaction)에 그룹화 하는 것에 의해 실현될 수 있습니다. 양쪽 모두의 갱신 작업이 정상적으로 행해졌을 경우에,`commit` 메소드를 호출해, 양쪽 모두의 갱신 결과를 데이타베이스에 반영합니다. 1 개(살) 또는 양쪽 모두가 실패했을 경우에는,`rollback` 메소드를 호출해, 갱신 작업이 실행되기 전의 값에 되돌립니다.

대부분의 JDBC 드라이버는 트랜잭션(transaction)라고 하는 개념을 지원합니다. JDBC 준거로서 지정되기 위해서(때문에)는, JDBC 드라이버가 트랜잭션(transaction)를 지원할 필요가 있습니다.

JDBC 2.0 표준 확장 기능 API 에서는,`Connection` 객체를 분산 트랜잭션(transaction)의 일부로 할 수가 있습니다. 즉 1 개의 트랜잭션(transaction)가 복수의 DBMS 서버라든지 서로 변할 수가 있습니다. `Connection` 객체가 분산 트랜잭션(transaction)의 일부인 경우는, 트랜잭션(transaction) 매니저가 `commit` 또는 `rollback` 메소드를 호출하는 타이밍을 결정합니다. `Connection` 객체가 분산 트랜잭션(transaction)에 관계하고 있는 경우에는, 이 때문에, 어플리케이션으로부터 접속의 개시 또는 종료의 타이밍에 영향을 주는 처리를 실시하지 말아 주세요.

`Connection` 객체를 분산 트랜잭션(transaction)에 관계시키려면 , 중간층의 서버의 분산 트랜잭션(transaction) 인프라스트럭쳐(infrastructure)와 함께 동작하도록(듯이) 구현된,`DataSource` 객체를 사용해 `Connection` 객체를 생성할 필요가 있습니다. `DriverManager` 에 의해 생성된 `Connection` 객체와 달리,`DetaSource` 객체와 같은 객체에 의해 생성된 `Connection` 객체는, 자동 위탁 모드가 디폴트로 무효가 됩니다. 한편,`DataSource` 객체의 표준적인 구현으로 생성되는 `Connection` 객체는,`DriverManager` 클래스에 의해 생성되는 `Connection` 객체와 완전하게 같게 됩니다.

#### 2.1. 8 트랜잭션(transaction)의 차단 레벨

DBMS 가 트랜잭션(transaction) 처리를 지원하는 경우, DBMS 에는, 2 개의 트랜잭션(transaction)가 1 개의 데이타베이스상에서 동시에 가동하고 있을 때 생길 수 있는, 잠재적인 경합을 관리할 방법이 몇개인가 있습니다. 사용자는, 잠재적인 경합을 해결하는데, DBMS 가 어느 정도의 주위를 기울일 필요가 있는지를 나타내는 트랜잭션(transaction)의 차단 레벨을 지정할 수가 있습니다. 예를 들어, 어느 트랜잭션(transaction)가 값을 변경해, 변경이 위탁 또는 롤백(rollback) 되기 전에, 2 번째의 트랜잭션(transaction)가 그 값을 읽어내면(자) 어떻게 될까요. 최초의 트랜잭션(transaction)가 롤백(rollback) 했을 경우, 2 번째의 트랜잭션(transaction)가 읽어낸, 변경된 값이 무효라고 하는 것이 허용 되는 것일까요. JDBC 사용자는, 다음의 코드를 사용해 (con 는 현재의 접속), 위탁되기 전에 값을 읽을 수 있도록(듯이) (더러워진 값의 읽기) 지시할 수가 있습니다.

>     con.setTransactionIsolation(TRANSACTION_READ_UNCOMMITTED);

트랜잭션(transaction)의 차단 레벨이 높아지면 과연, 경합을 피하기 위한 주의가 보다 많이 지불해집니다. `Connection` 인터페이스는, 트랜잭션(transaction)가 전혀 지원되지 않는 최저 레벨로부터, 1 개의 트랜잭션(transaction)가 데이타베이스상에서 조작하고 있는 동안에, 그 트랜잭션(transaction)가 읽어내고 있는 데이터에 대해서, 다른 트랜잭션(transaction)가 변경을 실시하지 않는다고 하는 최고 레벨까지, 5 단계의 레벨을 정의합니다. 상기의 예로 사용된 `TRANSACTION_READ_UNCOMMITTED` 의 레벨은, 최저 레벨의 1 개상입니다. 일반적으로, 차단의 레벨이 높아지면(자), 어플리케이션을 실행하는 속도는 저하합니다 (록킹에 의한 오버헤드가 증대해, 사용자 사이의 동시 사용이 저감 하기 위한(해)). 어느 차단 레벨을 사용할까를 결정할 때는, 개발자는 퍼포먼스상의 요구와 데이터의 일관성에 대해, 요구의 밸런스를 취할 필요가 있습니다. 물론, 실제로 지원되는 레벨은, 기반의 DBMS 의 능력에 의존합니다.

`Connection` 객체가 새롭게 생성되면(자), 그 트랜잭션(transaction)의 차단 레벨은, 드라이버에 의합니다만, 일반적으로의 경우에는 기반의 데이터 소스의 디폴트 값가 됩니다. 사용자는 메소드 `setIsolationLevel` 를 호출해, 트랜잭션(transaction)의 차단 레벨을 변경해, 그 접속 세션의 나머지에 대해서는 새로운 레벨을 유효하게 할 수 있습니다. 1 개의 트랜잭션(transaction)에 관해서만 트랜잭션(transaction)의 차단 레벨을 변경하려면 , 그 트랜잭션(transaction)내의 문장을 실행하기 전에 차단 레벨을 설정할 필요가 있습니다. 그리고, 트랜잭션(transaction)가 종료한 뒤에 그것을 리셋 합니다. 트랜잭션(transaction)의 한중간에 트랜잭션(transaction)의 차단 레벨을 변경하면(자), 메소드 `commit` 에의 즉시 호출의 트리거가 걸려, 그 시점까지 행해진 모든 변경이 데이타베이스에 반영되므로, 이것은 추천할 수 없습니다.

#### 2.1. 9 DBMS 자원의 해제

작성한 접속 및 문장이 필요없게 된 시점에서, 명시적으로 클로즈 하는 것을 추천합니다.

Java 프로그램 언어로 코드를 기술해, 외부 자원을 사용하고 있지 않는 경우는, 메모리 메니지먼트에 대해 걱정할 필요는 없습니다. 이미 사용되지 않는 객체는, 가비지 컬렉터에 의해 자동적으로 삭제되어 사용하고 있던 메모리는 해제됩니다. 메모리가 부족해 오면(자), 파기된 객체가 현재 닫고 있는 메모리를 민첩한 재사용으로서 사용할 수 있도록(듯이) 해 리사이클합니다.

다만, 어플리케이션에 의해 외부 자원이 사용되고 있는 경우, 즉 JDBC API 를 사용해 DBMS 에 액세스 하고 있는 경우는, 가비지 컬렉터에서는 그러한 자원 상태를 인식할 수 없습니다. 파기된 객체의 리사이클은 여전히 행해집니다만, Java heap에 비어 메모리가 많이 존재하고 있을 때는, 소량의 Java 의 가베지가 대량의 고가의 데이타베이스 자원을 오픈한 채로 하고 있는 것에도 불구하고, 가베지 컬렉트가 이따금 밖에 행해지지 않습니다. 따라서, 필요가 없어지면(자) 가능한 한 빨리 명시적으로 모든 접속을 `Connection.close` 로 클로즈 해, 모든 문장을 `Statement.close` 로 클로즈 해, 거기에 따라 가능한 한 빨리 DBMS 의 자원을 해제하는 것을 추천합니다. 어느 DBMS 와 다른 그것과는 차이가 있으므로, 이것은, 다른 복수의 DBMS 를 사용할 예정의 어플리케이션에 특별히 들어맞읍니다.

`Connection.isClosed` 메소드는,`Connection.close` 가 불려 간 뒤에 불려 갔을 때만,`true` 를 돌려준다고 하는 것이 보증되고 있습니다. 이 때문에, 접속이 유효한가 어떤가를 조사하는데는, 이 메소드는 기대가 되지 않습니다. 대신에, 전형적인 JDBC 클라이언트에서는, JDBC 의 조작을 시도했을 때에 throw 되는 예외를 캐치 하는 것으로, 접속이 무효가 되어 있는 것을 판단할 수 있습니다.

#### 2.1. 10 형 맵의 사용법

SQL 의 구조화형 및 `DISTINCT` 형은, SQL3 의 새로운 데이터형입니다. 이것들은, 사용자 정의의 형태 (UDT)이며, Java 프로그램 언어의 클래스에 커스텀 매핑 할 수 있습니다. SQL3 의 모든 데이터형과 같게, 표준적인 매핑을 가지고 있습니다만, 커스텀 매핑도 작성할 수 있습니다. 개개의 UDT 에 커스텀 매핑이 존재할지 어떨지는,`java.util.Map` 객체내에서 선언되고 있습니다. 이 `Map` 객체는, 접속에 관련지을 수 있는지, 메소드에게 건네집니다.

`Map` 객체에 엔트리를 추가하는 것에 의해 커스텀 매핑을 선언합니다. 이 엔트리에는, (1) 매핑 되려고 하고 있는 UDT 의 이름, 및 (2) UDT 가 매핑 하려고 하고 있는 Java 프로그램 언어안의 클래스의 `Class` 객체를 포함할 필요가 있습니다. 그 클래스는 그것 자신으로 특유의 매핑을 포함하게 됩니다. 덧붙여 이 클래스는,`SQLData` 인터페이스도 구현하고 있지 않으면 안됩니다.

커스텀 매핑을 지원하고 있는 JDBC 2.0 드라이버에 의해 생성된 개개의 `Connection` 는, 커스텀 매핑을 추가하기 위한 빈 상태(empty)의 형태 맵이 짜넣어집니다. 이 형태 맵은,`java.util.Map` 인터페이스의 인스턴스입니다. 이것은 Java 2 플랫폼의 새로운 기능으로,`java.util.Dictionary` 를 옮겨놓습니다. 커스텀 맵의 엔트리를 이 형태 맵에 추가할 때까지 는,`STRUCT` 및 `DISTINCT` 치의 모든 조작에는, 표준 매핑이 사용됩니다 (`STRUCT` 치의 경우는 `Struct` 인터페이스,`DISTINCT` 치의 경우는 기반이 되는 형태).

다음의 코드에서는, con 에 관련지을 수 있었던 형태 맵이 꺼내져 새로운 엔트리가 con 에 추가됩니다. 여기서, con 는 `Connection` 객체,`ADDRESSES` 는 SQL 구조화형입니다. 형태 맵이 변경된 후에, con 의 새로운 형태 맵으로서 설정해 있습니다.

>     java.util.Map map = con.getTypeMap();
>     map.put("SchemaName.ADDRESSES", Class.forName("Addresses"));
>     con.setTypeMap();

`Map` 객체의 map 는, con 에 관련지을 수 있었던 형태 맵으로, 이 코드의 실행 후에는 적어도, 1 개 (매핑이 벌써 추가되고 있는 경우는 복수)의 커스텀 매핑이 포함되어 있습니다. (많은 경우, 클래스를 생성하는 툴을 사용해) `Addresses` 클래스를 작성해 둡니다. `SQLData` 인터페이스를 구현하고 있지 않는 클래스를 제공하는 것은 잘못입니다. `Addresses` 클래스에는,`SQLData` 가 구현되고 있어`ADDRESSES` 의 각 속성에 대응하는 필드가 존재합니다. `ADDRESSES` 형의 값이 Java 프로그램 언어의 메소드로 조작되면(자), 디폴트로 `Addresses` 클래스의 인스턴스에 매핑 됩니다. 다른 형태의 맵이 명시적으로 메소드에게 건네지지 않는 경우는, 접속에 관련지을 수 있고 있는 형태 맵이, 디폴트의 형태 맵이 됩니다.

UDT 의 이름은, 완전하게 수식된 이름이 아니면 안됩니다. 일부의 DBMS 에서는,`catalogName.schemaName.UDTName` 의 형식이 사용됩니다. 그러나, 많은 DBMS 에서는, 이 형식은 사용되고 있지 않습니다. 예를 들어, 카탈로그명을 포함하지 않고 schema명이 사용됩니다. 각 DBMS 에 적절한 형식을 사용해 주세요. `DatabaseMetaData` 의 `getCatalogs`,`getCatalogTerm`,`getCatalogSeparator`,`getSchemas`, 및 `getSchemaTerm` 메소드를 사용하면(자), DBMS 의 카탈로그명, schema명, 카탈로그로서 바람직한 어구, 및 카탈로그명과 테이블명의 사이에 사용되고 있는 단락 문자에 관한 정보를 취득할 수 있습니다.

기존의 형태 맵을 수정하는 대신에, 어플리케이션으로 다른 형태 맵에 옮겨놓을 수가 있습니다. 다음의 코드에 나타내도록(듯이),`Connection` 의 `setTypeMap` 메소드를 사용합니다. 새로운 형태 맵을 작성해, 그 형태 맵에 2 개의 엔트리 (각각은, SQL UDT 명 및 그 형태의 값의 매핑처의 클래스를 가진다)를 추가합니다. 다음에,`Connection` 의 con 에 관련지을 수 있었던 형태 맵으로서 새로운 형태 맵을 인스톨 합니다.

>     java.util.Map newConnectionMap = new java.util.HashTable();
>     newConnectionMap.put(
>          "SchemaName.UDTName1", Class.forName("className1"));
>     newConnectionMap.put(
>          "SchemaName.UDTName2", Class.forName("className2"));
>     con.setTypeMap(newConnectionMap);

이것으로,`Connection` 객체의 con 에도라고도와 관련지을 수 있고 있던 형태 맵은,`Map` 객체의 newConnectionMap 에 옮겨집니다. newConnectionMap 는, 다음으로 옮겨질 때까지, 커스텀형 맵으로서 사용됩니다. 이 예에서는, 새로운 형태 맵을 작성할 경우에,`HashTable` 클래스의 디폴트의 생성자 이 사용되고 있습니다. 이 클래스는, Java 2 플랫폼 API 로 제공되고 있는 `java.util.Map` 의 구현의 1 개입니다. 그 외의 구현을 사용할 수도 있습니다.

전술의 몇개의 예에서는, 접속에 관련지을 수 있었던 형태 맵이, 추가의 매핑을 짜넣도록(듯이) 변경되거나 완전히 다른 형태 맵으로서 설정되었습니다. 어느 경우도, JDBC 의 형태와 Java 프로그램 언어의 형태를 커스텀 매핑 한다고 하는 점에서는, 접속의 형태 맵이 디폴트 값가 됩니다. 다음의 예에서는, 다른 형태 맵을 사용하는 메소드를 제공하는 것에 의해, 접속의 형태 맵을 옮겨놓는 방법을 나타냅니다.

메소드의 구현에 UDT 의 커스텀 매핑을 포함할지도 모르는 경우에는, 형태 맵을 지정하는 메소드와 지정하지 않는 메소드의 2 개의 버젼을 준비합니다. 형태 맵을 메소드에 건네주었을 경우에는, 그 형태 맵이, 접속에 관련지을 수 있었던 형태 맵 대신에 사용됩니다. 예를 들어,`Array` 의 `getArray` 및 `getResultSet` 메소드에는, 형태 맵을 지정하는 메소드와 지정하지 않는 메소드가 있습니다. 형태 맵이 메소드에게 건네졌을 경우는, 그 형태 맵을 사용해 배열 요소가 매핑 됩니다. 형태 맵이 지정되어 있지 않은 경우는, 접속에 관련지을 수 있었던 형태 맵이 메소드로 사용됩니다.

메소드에 형태 맵을 건네주면(자), 같은 사용자 정의의 형태의 값에 다른 매핑을 설정할 수 있습니다. 예를 들어, 2 개의 어플리케이션이 같은 접속을 사용해, 같은 열의 값을 조작하고 있는 경우, 한편은, 접속에 관련지을 수 있었던 형태 맵을 사용해, 한편은 적절한 메소드에 인수로서 건네준 다른 형태의 맵을 사용할 수가 있습니다.

다음의 코드에서는, 새로운 형태 맵을 작성해,`Array` 의 `getArray` 메소드에 파라미터로서 건네주고 있습니다.

>     java.util.Map arrayMap = new java.util.HashTable();
>     arrayMap.put("SchemaName.DIMENSIONS", Class.forName("Dimensions"));
>     Dimensions [] d = (Dimensions []) array.getArray(arrayMap);

2 행 째로, 새로운 형태 맵 arrayMap 에, 완전하게 수식된 SQL 구조화형의 이름 (`SchemaName.DIMENSIONS`) 및 Java 클래스 객체 (`Class.forName("Dimensions")`)의 엔트리가 주어지고 있습니다. 이 결과, Java 의 `Dimensions` 형과 SQL 의 `DIMENSIONS` 형의 사이에 매핑이 확립됩니다. 3 행 째로는, arrayMap 가 형태 맵으로서 지정되어 이 `Array` 객체의 내용의 매핑에 사용됩니다. 기본형은,`SchemaName.DIMENSIONS` 입니다.

`getArray` 메소드에서는, array 로 지정된 SQL3 `ARRAY` 치의 요소가 생성됩니다. 이 때, 각 요소는, arrayMap 로 지정되고 있는 매핑에 응해 매핑 됩니다. 즉, 각 `DIMENSIONS` 치의 속성을 `Dimensions` 객체의 필드에 매핑 하는 것에 의해,`Schema.DIMENSIONS` 형의 값인 각 요소가,`Dimensions` 클래스의 인스턴스에 변환됩니다. 배열의 기본으로 되어 있는 형태가 arrayMap 로 명명되고 있는 UDT 명으로 일치하지 않는 경우는, 드라이버에 의해, 배열의 요소가 표준적인 매핑에 응해 변환됩니다. 또,`getArray` 메소드에 형태 맵이 지정되어 있지 않은 경우는, 드라이버에서는, 접속의 형태 맵으로 지정되고 있는 매핑이 사용됩니다. 그 형태 맵에 `Schema.DIMENSIONS` 의 엔트리가 존재하지 않는 경우는, 드라이버에서는 표준적인 매핑이 대신에 사용됩니다.

[목차] [전의 항목] [다음의 항목]

Copyright © 1999, Sun Microsystems, Inc. All rights reserved.