728x90
반응형
Data Mapper로 프로그래밍하기: The API
SqlMapClient API는 간단하고 최소한으로 되어 있다. 이것은 프로그래머에게 4가지(SQL Map를 설정하기, SQL update문
(insert와 delete문을 포함해서) 수행하기, 하나의 객체를 위한 쿼리 수행하기, 그리고 객체의 리스트를 위한 쿼리 수행하
기) 중요한 기능을 할 수 있는 능력을 제공한다.
설정
SQL Map을 설정하는 것은 당신이 SQL Map XML정의파일과 SQL Map설정파일을 생성하는것이다. SqlMapClient인스턴스는
SqlMapClientBuilder를 사용해서 빌드된다. 이 클래스는 buildSqlMap()이라는 하나의 중요한 정적 메소드를 가진다.
buildSqlMap()메소드는 간단하게 sqlMap-config.xml의 내용을 읽을수 있는 Reader인스턴스를 가져온다.
String resource = “com/ibatis/example/sqlMap-config.xml”;
Reader reader = Resources.getResourceAsReader (resource);
SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMap(reader);
트랜잭션
디폴트에 의하면 SqlMapClient인스턴스에서 어느 executeXxxx()메소드를 호출하는 것은 자동커밋/롤백(autocommit/
rollback)을 하는것이다. 이것은 executeXxxx()의 각각의 호출이 하나의 작업단위가 되는 것을 의미한다. 이것은
정말로 간단하다. 하지만 하나의 작업단위로 수행해야할 많은 수의 statement(이를 테면 그룹처럼 모두 성공하거나 실패
하는것)를 가진다면 좋은생각이 아니다. 이것은 트랜잭션이 작동하는 시점이다.
만약 당신이 전역(SQL Map설정파일에 의해 설정된) 트랜잭션을 사용한다면 당신은 자동커밋을 사용할수 있고 여전히 작업
단위 행위를 달성할수 있다. 어쨌든 이것은 트랜잭션 범위 경계는 성능원인에 영향을 끼친다. 그리고 이것은 connection pool
과 데이터베이스 연결 초기화에 트래픽을 감소시킨다.
SqlMapClient인터페이스는 트랜잭션경계를 지정하기 위해 메소드를 가진다. 트랜잭션이 시작되고 SqlMapClient인터페이스
의 다음과 같은 메소드를 사용함으로써 커밋되고/되거나 롤백된다.
public void startTransaction () throws SQLException
public void commitTransaction () throws SQLException
public void endTransaction () throws SQLException
트랜잭션을 시작함으로써 당신은 connection pool로부터 connection을 가져오고 SQL쿼리와 update를 가져오기 위해 열린다.
트랜잭션을 사용하는 에제는 다음과 같다.
private Reader reader =
new Resources.getResourceAsReader ("com/ibatis/example/sqlMap-config.xml");
35
private SqlMapClient sqlMap = XmlSqlMapBuilder.buildSqlMap(reader);
public updateItemDescription (String itemId, String newDescription)
throws SQLException {
try {
sqlMap.startTransaction ();
Item item = (Item) sqlMap.queryForObject ("getItem", itemId);
item.setDescription (newDescription);
sqlMap.update ("updateItem", item);
sqlMap.commitTransaction ();
} finally {
sqlMap.endTransaction ();
}
}
endTransaction()가 에러에도 불구하고 호출되는 방법에 주의하라. 이것은 정화(cleanup)을 확실히 하기 위해서 중요한 단
계이다. 그 규칙은 만약 당신이 startTransaction()을 호출한다면 endTransaction()을 받드시 호출해야 한다. (당신이 커밋을
하거나 하지않더라도)
주의! 트랜잭션은 내포될수 없다. 한 개이상의 같은 쓰레드로부터 .startTransaction()을 호출하는 것은 commit()나
rollback()을 호출하기 전에 던져질 예외를 야기한다. 반면에 각각의 쓰레드는 SqlMapClient 인스턴스마다 적어도 하나의
열려있는 트랜잭션 가질수 있다.
주의! SqlMapClient 트랜잭션은 저장 트랜잭션 객체를 위해 자바의 ThreadLocal을 사용한다. 이것은 각각의
startTransaction()을 호출하는 쓰레드가 그들의 트랜잭션을 위해 유일한 Connection객체를 가질것이라는걸 의미한다. 데
이터소스로 connection을 반환(또는 connection을 닫는)하는 유일한 방법은 commitTransaction()이나 endTransaction()을
호출하는것이다. 아무것도 하지않으면 당신의 pool이 connection이 바닥나거나 잠기게 되는 현상을 야기할것이다.
자동 트랜잭션
명시적으로 트랜잭션을 사용하는 것이 매우 추천되는 사항임에도 불구하고 간단한 요구사항(대개는 읽기전용)을 위해 사용
되는 간략화된 의미론이 있다. 만약 당신이 startTransaction(), commitTransaction() 그리고 endTransaction()메소드를 사용해
서 명시적으로 트랜잭션의 경계를 지정하지 않는다면 그들은 위에서 보여진것처럼 트랜잭션범위의 밖에서 statement를 수행
할때마다 자동으로 호출될것이다. 예를 들면
private Reader reader =
new Resources.getResourceAsReader ("com/ibatis/example/sqlMap-config.xml");
private SqlMapClient sqlMap = XmlSqlMapBuilder.buildSqlMap(reader);
public updateItemDescription (String itemId, String newDescription)
throws SQLException {
try {
Item item = (Item) sqlMap.queryForObject ("getItem", itemId);
item.setDescription (“TX1”);
//No transaction demarcated, so transaction will be automatic (implied)
sqlMap.update ("updateItem", item);
item.setDescription (newDescription);
item.setDescription (“TX2”);
//No transaction demarcated, so transaction will be automatic (implied)
sqlMap.update("updateItem", item);
} catch (SQLException e) { throw (SQLException) e.fillInStackTrace(); }
}
주의! 자동 트랜잭션을 사용할 때 주의하라. 그들이 매력이 있음에도 불구하고 당신은 데이터베이스에 하나의 update보다 더
많은 작업량이 요구된다면 문제를 일으킬것이다. 위 예제에서 “updateItem”의 두번째 호출은 실패한다면 item description은
처음 새로운 “TX1”의 description으로 여전히 업데이트 될 것이다.(이를 테면 이것은 트랜잭션 행위가 아니다.)
전역(분산된) 트랜잭션
36
SQL Maps 프레임워크는 전역 트랜잭션을 잘 지원한다. 분산 트랜잭션처럼 알려져 있는 전역 트랜잭션은 당신에게 같은 작
업단위에서 다중 데이터베이스(또는 JTA호환 자원) update를 가능하게 할 것이다.(이를 테면 다중 데이터베이스 update는
그룹처럼 성공하거나 실패할수 있다.)
외 부적인 / 프 로그래적인 전역 트랜잭션
당신은 외부적으로(-프로그래적(손에 의해 코딩되는)) 또는 공통적인 EJB처럼 다른 프레임워크를 구현함으로써 전역 트랜
잭션 관리를 선택할수 있다. EJB를 사용하면 당신은 EJB배치서술자에서 선언적인 트랜잭션 경계를 지정할수 있다. 하지만
이것은 이 문서의 범위를 벋어난다. 외부적또는 프로그래밍적 전역 트랜잭션을 지원하기 위해서 당신은 SQL Map설정파일
에서 <transactionManager> type속성을 “EXTERNAL”으로 설정해야 한다. 외부적으로 제어되는 전역 트랜잭션을 사용할
때 SQL Map트랜잭션 제어 메소드는 다소 불필요하다. 외부 트랜잭션 관리자에 의해 트랜잭션의 시작, 커밋, 롤백이 제어되
기 때문이다. 어쨌든 SqlMapClient의 startTransaction(), commitTransaction() 그리고 endTransaction() 메소드를 사용해서
당신의 트랜잭션의 경계를 지정하는 것은 성능향상에 도움을 준다. 이런 메소드를 계속적으로 사용함으로써 당신은 일관
적인 프로그래밍 패러다임을 유지할 것이다. Connection pool으로부터 connection을 위한 요청 횟수를 제거할 수 있을것이
다. 다른 애플리케이션 서버와 트랜잭션 관리자는 다른 규칙을 사용한다. 반면에 간단한 고려사항은 전역 트랜잭션을 사용
하기 위해 SQL Map코드를 요구되는 변경사항이 없다.
관리되는 전역 트랜잭션
SQL Map프레임워크는 당신을 위해 전역 트랜잭션를 관리할수 있다. 관리되는 전역 트랜잭션을 사용하기 위해서는 당신은
SQL Map설정파일에 <transactionManager> type 속성을 “JTA”로 설정해야만 하고 “UserTransaction”을 SqlMapClient인스턴
스가 UserTransaction인스턴스를 찾는곳에 전체 JNDI이름에 셋팅해야 한다. 전체 설정방법에 대해서는
<transactionManager>부분을 보라.
전역 트랜잭션를 위한 프로그래밍은 크게 다르지 않다. 어쨌든 몇가지 작은 고려사항이 있다. 예제를 보라.
try {
orderSqlMap.startTransaction();
storeSqlMap.startTransaction();
orderSqlMap.insertOrder(…);
orderSqlMap.updateQuantity(…);
storeSqlMap.commitTransaction();
orderSqlMap.commitTransaction();
} finally {
try {
storeSqlMap.endTransaction()
} finally {
orderSqlMap.endTransaction()
}
}
이 예제에서 두 개의 다른 데이터베이스를 사용하는 것을 가정하는 두 개의 SqlMapClient인스턴스가 있다. 트랜잭션을 사
용하기 위해 사용되는 첫번째 SqlMapClient(orderSqlMap)는 역시 전역 트랜잭션을 시작할 것이다. 그 후, 다른 모든 행위는
같은 SqlMapClient(orderSqlMap)이 commitTransaction()과 endTransaction()을 호출할때까지 전역 트랜잭션의 한부분처럼
간주된다. 전역 트랜잭션이 커밋되는 시점에 모든 작업이 승인된다.
경고! 이것들이 간단하게 모임에도 불구하고 당신이 전역트랜잭션을 지나치게 사용하지 않도록 하는 것은 중요하다. 당신의
애플리케이션서버와 데이터베이스 드라이버를 위해 추가적인 복잡한 설정이 요구되는 만큼 성능에 문제가 있을수 있다. 이것
이 쉬워 보이지만 당신은 몇가지 어려움을 겪게 될것이다. EJB는 당신이 분산 트랜잭션을 요구하는 작업을 위해 세션 EJB를
사용을 좀더 쉽게 하기 위해서 좀더 많은 지원과 사용을 돕는 툴이 필요하다는 것을 기억해라. SQL Map전역 트랜잭션을 사용
하는 JPetStore라는 예제 애플리케이션은 www.ibatis.com에서 찾을수 있을것이다.

 

728x90
반응형
블로그 이미지

nineDeveloper

안녕하세요 현직 개발자 입니다 ~ 빠르게 변화하는 세상에 뒤쳐지지 않도록 우리모두 열심히 공부합시다 ~! 개발공부는 넘나 재미있는 것~!

,