결과 집합 확장기능

JDBC 2.0 표준에서 제공하는 기능인 Scrollable, Updatable 결과 집합의 확장기능을 설명합니다.

JDBC 2.0 표준

JDBC 2.0 표준에서는 scrollability, positioning, sensitivity, updatability에 대한 확장기능을 제공합니다.

  • 결과 집합 타입에 의해 scrollability, positioning, sensitivity가 결정됩니다.

  • 동시성 타입에 의해 updatability가 결정됩니다.

Scrollability, Positioning, Sensitivity

Scrollability, Positioning은 결과 집합에 대해 정방향뿐만 아니라 역방향으로도 움직일 수 있고, 상대 위치나 절대 위치 등의 임의의 위치로 움직일 수 있는 기능입니다. 여기서 상대 위치는 현재 열의 위치로부터 정방향 또는 역방향으로의 이동을 말하고, 절대 위치는 결과 집합의 시작이나 끝에서부터의 이동을 말합니다.

Scrollability, Positioning 결과 집합을 생성할 때는 반드시 Sensitivity를 설정해야 하는데, 이는 현재의 결과 집합에 관계없이 데이터베이스에 적용된 변경 사항을 반영할 것인지의 여부를 결정합니다. Sensitivity는 데이터베이스에 적용된 변경 사항이 바로 적용되어 새로운 데이터를 볼 수 있습니다. 반면에 Insensitivity는 최초 결과 집합이 생성된 시점의 데이터만 볼 수 있습니다.

결과 집합을 생성할 때 결정할 수 있는 결과 집합의 타입은 아래와 같습니다.

  • ResultSet.TYPE_FORWARD_ONLY

  • ResultSet.TYPE_SCROLL_SENSITIVE

  • ResultSet.TYPE_SCROLL_INSENSITIVE

Updatability

Updatability는 결과 집합에 직접 수정한 후에 데이터베이스에 반영할 수 있는 기능입니다. 예를 들어 새로운 열을 추가하거나 기존의 열을 지우거나 수정하는 것이 이에 해당됩니다.

결과 집합을 생성할 때 결정할 수 있는 동시성 타입은 아래와 같습니다.

  • ResultSet.CONCUR_UPDATABLE

  • ResultSet.CONCUR_READ_ONLY


Scrollable, Updatable 결과 집합 생성

Statement 객체 생성

tbJDBC에서는 Connection 클래스에 아래와 같은 메소드를 제공합니다.

  • Statement createStatement(int resultSetType, int resultSetConcurrency)

  • PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)

  • CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency)

아래는 Statement 객체를 생성하는 예입니다.

Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
                                      ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery("SELECT empno FROM emp");

결과 집합 특성 확인

Statement, PreparedStatement, CallableStatement 객체를 생성한 후에는 아래의 메소드를 사용하여 결과 집합 타입과 동시성 타입을 확인할 수 있습니다.

  • int getResultSetType() throws SQLException

  • int getResultSetConcurrent() throws SQLException

제약 사항

Updatable 결과 집합을 생성할 때는 아래와 같은 제약 사항이 존재합니다.

  • 오직 하나의 테이블에 대한 질의문만 사용할 수 있고, 조인(join)은 사용할 수 없습니다.

  • 'SELECT *'와 같은 형태는 사용할 수 없고, 'SELECT T.*'와 같은 형태만 사용할 수 있습니다.

  • 오직 테이블의 컬럼에 대해서만 질의문을 사용할 수 있습니다.

Scroll-sensitive 결과 집합을 생성할 때는 아래와 같은 제약 사항이 존재합니다.

  • 오직 하나의 테이블에 대한 질의문만 사용할 수 있습니다.

  • 'SELECT *'와 같은 형태는 사용할 수 없고, 'SELECT t.*'와 같은 형태만 사용할 수 있습니다.


Scrollable 결과 집합 탐색

아래는 Scrollable 결과 집합을 위해 제공되는 메소드로, 새로운 위치로 이동할 수 있습니다.

메소드
설명

boolean next() throws

SQLException

현재 위치에서 다음 열로 이동

(만약더이상 다음 열이 존재하지 않는 경우, false를 반환)

boolean previous() throws

SQLException

현재 위치에서 이전 열로 이동

(만약더이상 이전 열이 존재하지 않는 경우, false를 반환)

boolean first() throws

SQLException

결과 집합의 첫 번째 열로 이동

(만약 열 데이터가 하나도 없을 경우, false를 반환)

boolean last() throws

SQLException

결과 집합의 마지막 열로 이동

(만약 열 데이터가 하나도 없을 경우, false를 반환)

boolean absolute(int row) throws SQLException

결과 집합의 처음이나 마지막 열의 위치에서부터 정해진 값만큼 절대 위치로 이동

  • 입력 값이 양수인 경우: 처음 열부터 정방향으로 이동 입력 값이음수인 경우에: 마지막 열부터 역방향으로 이동

  • 결과 집합의 개수보다 더 큰 양수 값을 사용할 경우: 마지막 열 다음으로 이동, 이는 afterLast()와 같은 효과를 가짐

  • 결과 집합의 개수보다 더 큰 음수 값을 사용할 경우: beforeFirst()와 같은 효과를 가짐

boolean relative(int row) throws SQLException

현재 열의 위치로부터 시작하여 양수 값이면 정방향으로 이동하고, 음수 값 이면 역방향으로 이동

  • 결과 집합의 개수보다 더 큰 양수 값을 사용할 경우: 마지막 열 다음으로 이동, 이는 afterLast()와 같은 효과를 가짐

  • 결과 집합의 개수보다 더 큰 음수 값을 사용한 경우: beforeFirst()와 같은 효과를 가짐

(주의: 반드시 현재 열의 위치가 적절해야 함. 처음 열의 위치 이전이나 마지막 열의 위치 다음에서부터 상대 위치로의 이동은 할 수 없으며, SQLException을 발생시킴)

void beforeFirst() throws SQLException

결과 집합의 첫 번째 열 이전으로 이동

  • 이는 정방향으로 결과 집합을 탐색할 때의 상태이며 바로 사용할 수 있는 열 데이터는 없음

void afterLast() throws SQLException

결과 집합의 마지막 열 다음으로 이동

  • 이는 역방향으로 결과 집합을 탐색할 때의 상태이며 바로 사용할 수 있는 열 데이터는 없음

현재의 위치 정보를 알기 위해 tbJDBC에서는 아래와 같은 메소드를 제공합니다.

메소드
설명

int getRow() throws

SQLException

현재 열의 위치를 반환하며, 적합한 열의 위치가 아닌 경우에는 0을 반환

boolean isFirst() throws

SQLException

현재 열의 위치가 첫 번째 열인지 확인

boolean isLast() throws

SQLException

현재 열의 위치가 마지막 열인지 확인

boolean isBeforeFirst()

throws SQLException

현재 열의 위치가 첫 번째 열의 이전 열인지 확인

boolean isAfterLast()

throws SQLException

현재 열의 위치가 마지막 열의 다음 열인지 확인


Updatable 결과 집합 탐색

사용자는 Updatable 결과 집합을 이용하여 열의 데이터를 업데이트할 수 있고, 삭제할 수도 있으며, 새로운 열의 데이터를 입력할 수도 있습니다.

UPDATE나 INSERT를 수행한 후에는 반드시 별도의 단계를 거쳐 데이터베이스에 변경 사항을 반영해야 합니다. 그렇지 않으면 변경된 모든 데이터는 소멸됩니다.

반면에 DELETE를 수행한 경우에는 별도의 단계 없이 즉시 데이터베이스에 반영됩니다.

INSERT

INSERT 작업은 다음의 과정을 거쳐 데이터베이스에 반영됩니다.

  1. moveToInsertRow() 메소드를 이용하여 INSERT를 수행하기 위한 임시 열 데이터 저장 공간으로 이동합니다. 결과 집합은 기존의 열의 위치를 내부적으로 기억하고 있으므로 moveToCurrentRow() 메소드를 사용할 경우 원래 열의 위치로 이동할 수 있습니다.

  2. 적절한 updateXXX() 메소드를 수행하여 컬럼의 데이터를 작성합니다. 만약 특정 컬럼의 데이터를 작성하지 않는다면, NULL 상태로 남아 있게 됩니다.

  3. insertRow() 메소드를 수행하여 데이터베이스에 반영합니다.

만약 INSERT를 수행한 후에 이를 취소하려면, 다른 열의 위치로 이동하여 원래의 데이터로 복원하면 됩니다. 그러나 반드시 아래 사항을 주의해야 합니다.

  • insertRow() 메소드를 수행한 경우 데이터베이스에 반영되므로 롤백하기 전에는 취소되지 않습니다.

  • 어떠한 결과 집합의 타입도 INSERT 작업에 의해 수행된 열의 데이터를 볼 수 없습니다.

INSERT 작업 수행 예시

rs.moveToInsertRow(); 
rs.updateString(1, "tibero");
rs.insertRow(); 
rs.moveToCurrentRow();

UPDATE

UPDATE 작업은 아래의 두 단계를 거쳐야 데이터베이스에 최종으로 반영됩니다.

  1. updateXXX() 메소드를 수행합니다.

  2. updateRow() 메소드를 수행하여 데이터베이스에 반영합니다. 이때 auto-commit 모드에 따라 커밋이 될 수도 있습니다. 만약 UPDATE를 수행한 후에 이를 취소하려면, cancelRowUpdates() 메소드를 수행하거나 다른 열의 위치로 이동할 경우 원래의 데이터로 복원하면 됩니다. 그러나 updateRow() 메소드를 수행한 경우라면 데이터베이스에 반영이 되므로 롤백하기 전에는 취소되지 않음을 주의해야 합니다.

UPDATE 작업 수행 예시

rs.absolute(5); 
rs.updateString(1, "tibero"); 
rs.updateRow();

DELETE

DELETE 작업을 수행할 때는 반드시 아래의 사항을 주의합니다.

  • DELETE 작업을 수행할 경우 데이터베이스에 바로 적용되므로 auto-commit 모드의 설정 값에 따라 바로 커밋이 될 수도 있습니다.

  • 사용자에 의해 지워진 열 데이터의 경우 데이터베이스에는 반영되지만 결과 집합 자체에는 남아 있게 됩니다. 반대로 Scrollable 결과 집합인 경우에는 바로 재조정이 일어납니다. 즉, 현재 열의 위치는 바로 이전의 열의 데이터를 가리키게 되고, 다음 열의 위치는 자동으로 당겨지게 됩니다.

아래의 메소드를 사용하여 DELETE 작업을 수행할 수 있습니다.

void deleteRow() throws SQLException

DELETE 작업 수행 예시

rs.absolute(5); 
rs.deleteRow();

Last updated