내용 목차
본 장에서는 JDBC 2.0 표준에서 제공하는 기능인 Scrollable, Updatable 결과 집합의 확장기능을 설명한다.
JDBC 2.0 표준에서는 scrollability, positioning, sensitivity, updatability에 대한 확장기능을 제공한다.
결과 집합 타입에 의해 scrollability, positioning, sensitivity가 결정된다.
동시성 타입에 의해 updatability가 결정된다.
Scrollability, Positioning은 결과 집합에 대해 정방향뿐만 아니라 역방향으로도 움직일 수 있고, 상대 위치나 절대 위치 등의 임의의 위치로 움직일 수 있는 기능이다. 여기서 상대 위치는 현재 열의 위치로부터 정방향 또는 역방향으로의 이동을 말하고, 절대 위치는 결과 집합의 시작이나 끝에서부터의 이동을 말한다.
Scrollablility 기능을 사용할 경우 결과 집합의 모든 열은 사용자의 메모리에 로드되기 때문에 이를 주의해야 한다. 그리고 될 수 있으면 용량이 큰 데이터를 갖는 결과 집합은 사용하지 말 것을 권장한다.
Scrollability, Positioning 결과 집합을 생성할 때는 반드시 Sensitivity를 설정해야 하는데, 이는 현재의 결과 집합에 관계없이 데이터베이스에 적용된 변경 사항을 반영할 것인지의 여부를 결정한다.
Sensitivity는 데이터베이스에 적용된 변경 사항이 바로 적용되어 새로운 데이터를 볼 수 있다. 반면에 Insensitivity는 최초 결과 집합이 생성된 시점의 데이터만 볼 수 있다.
결과 집합을 생성할 때 결정할 수 있는 결과 집합의 타입은 다음과 같다.
ResultSet.TYPE_FORWARD_ONLY
ResultSet.TYPE_SCROLL_SENSITIVE
ResultSet.TYPE_SCROLL_INSENSITIVE
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 결과 집합을 위해 제공되는 메소드로, 새로운 위치로 이동할 수 있다.
메소드 | 설명 |
---|---|
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 결과 집합을 이용하여 열의 데이터를 업데이트할 수 있고, 삭제할 수도 있으며, 새로운 열의 데이터를 입력할 수도 있다.
UPDATE나 INSERT를 수행한 후에는 반드시 별도의 단계를 거쳐 데이터베이스에 변경 사항을 반영해야 한다. 그렇지 않으면 변경된 모든 데이터는 소멸된다. 반면에 DELETE를 수행한 경우에는 별도의 단계 없이 즉시 데이터베이스에 반영된다.
INSERT 작업은 다음의 과정을 거쳐 데이터베이스에 반영된다.
moveToInsertRow() 메소드를 이용하여 INSERT를 수행하기 위한 임시 열 데이터 저장 공간으로 이동한다. 결과 집합은 기존의 열의 위치를 내부적으로 기억하고 있으므로 moveToCurrentRow() 메소드를 사용할 경우 원래 열의 위치로 이동할 수 있다.
적절한 updateXXX() 메소드를 수행하여 컬럼의 데이터를 작성한다. 만약 특정 컬럼의 데이터를 작성하지 않는다면, NULL 상태로 남아 있게 된다.
insertRow() 메소드를 수행하여 데이터베이스에 반영한다.
만약 INSERT를 수행한 후에 이를 취소하려면, 다른 열의 위치로 이동하여 원래의 데이터로 복원하면 된다. 그러나 반드시 다음의 사항을 주의해야 한다.
insertRow() 메소드를 수행한 경우 데이터베이스에 반영이 되므로 롤백하기 전에는 취소되지 않는다.
어떠한 결과 집합의 타입도 INSERT 작업에 의해 수행된 열의 데이터를 볼 수 없다.
다음은 INSERT 작업을 수행하는 예이다.
rs.moveToInsertRow();
rs.updateString(1, "tibero");
rs.insertRow();
rs.moveToCurrentRow();
UPDATE 작업은 다음의 두 단계를 거쳐야 데이터베이스에 최종으로 반영된다.
updateXXX() 메소드를 수행한다.
updateRow() 메소드를 수행하여 데이터베이스에 반영한다. 이때 auto-commit 모드에 따라 커밋이 될 수도 있다.
만약 UPDATE를 수행한 후에 이를 취소하려면, cancelRowUpdates() 메소드를 수행하거나 다른 열의 위치로 이동할 경우 원래의 데이터로 복원하면 된다. 그러나 updateRow() 메소드를 수행한 경우라면 데이터베이스에 반영이 되므로 롤백하기 전에는 취소되지 않음을 주의해야 한다.
다음은 UPDATE 작업을 수행하는 예이다.
rs.absolute(5);
rs.updateString(1, "tibero");
rs.updateRow();
DELETE 작업을 수행할 때는 반드시 다음의 사항을 주의해야 한다.
DELETE 작업을 수행할 경우 데이터베이스에 바로 적용되므로 auto-commit 모드의 설정 값에 따라 바로 커밋이 될 수도 있다.
사용자에 의해 지워진 열 데이터의 경우 데이터베이스에는 반영되지만 결과 집합 자체에는 남아 있게 된다. 반대로 Scrollable 결과 집합인 경우에는 바로 재조정이 일어난다. 즉, 현재 열의 위치는 바로 이전의 열의 데이터를 가리키게 되고, 다음 열의 위치는 자동으로 당겨지게 된다.
다음의 메소드를 사용하여 DELETE 작업을 수행할 수 있다.
void deleteRow() throws SQLException
다음은 DELETE 작업을 수행하는 예이다.
rs.absolute(5); rs.deleteRow();