트랜잭션 서비스 사용
트랜잭션은 비즈니스의 통합된 일부입니다. 일반 비즈니스 트랜잭션은 두 개 이상의 관련 부분 사이 자산 이동과 관련되어 있습니다. 정확성을 요하는 기록은 보통 하나 이상의 데이터베이스에 저장됩니다. 이 정보는 비즈니스 작업에 꼭 필요하기 때문에 항상 유효하고, 현재성을 가지고, 신뢰할 수 있어야 합니다. 초보 프로그래머에게는 트랜잭션 처리가 어려울 수 있습니다. J2EE 플랫폼은 종속 가능한 트랜잭션 처리 응용 프로그램 전개를 쉽게 해주는 여러 추상적 개념을 제공합니다. 이 장에서는 Sun ONE Application Server의 J2EE 트랜잭션 및 트랜잭션 지원을 설명합니다.
이 장에서는 일반적으로 Java 트랜잭션, 구체적으로는 Sun ONE Application Server에 포함되어 있는 트랜잭션 지원에 대해 설명합니다.
이 장에서는 다음 내용을 설명합니다.
트랜잭션 정보
비즈니스 트랜잭션을 에뮬레이트하려면 프로그램이 여러 단계를 수행해야 할 수 있습니다. 예를 들어, 재무 프로그램이 다음 의사 코드에 나열된 단계를 수행하면 자금을 수표 계좌에서 예금 계좌로 이체할 수 있습니다.
앞의 의사 코드에서 begin 및 commit 명령은 트랜잭션 경계를 표시합니다. 트랜잭션을 완료하려면 세 단계가 모두 완료되어야 합니다. 세 단계가 모두 완료되지 못하면 데이터 통합이 손상될 수 있습니다.
이 보장을 원자성이라고 합니다. 트랜잭션은 commit 또는 rollback 명령으로 끝납니다. 트랜잭션을 완결하면 트랜잭션 경계 내의 명령으로 수행한 모든 수정이 저장 및 지속됩니다. 변경은 영구적이며 이후 시스템 장애가 일어나도 그대로 유지됩니다. 트랜잭션 내의 명령 중 하나라도 실패하면 트랜잭션 전체가 롤백하며, 그 때까지 트랜잭션 내에서 실행된 모든 명령은 취소됩니다. 예를 들어, 의사 코드의 credit 단계 중 디스크 드라이브에 오류가 발생하면, 트랜잭션은 롤백되고 debit 명령으로 수행되었던 데이터 변경도 모두 취소됩니다.
트랜잭션이 실패해도 트랜잭션 계정 잔액은 여전히 유지되기 때문에 데이터 통합이 손상되지 않습니다. 트랜잭션 작동의 이런 측면을 트랜잭션 일관성이라 합니다.
트랜잭션 서비스는 고립화도 제공합니다. 이것은 트랜잭션이 완결 또는 롤백되기 전까지는 트랜잭션 내 구문을 다른 응용 프로그램에서 관찰할 수 없음을 의미합니다. 일단 트랜잭션이 완결되면 이 완결된 트랜잭션은 응용 프로그램 및 스레드가 안전하게 관찰할 수 있습니다.
J2EE 트랜잭션
J2EE의 트랜잭션 처리는 트랜잭션 관리자, 응용 프로그램 서버, 자원 관리자, 자원 어댑터 및 사용자 응용 프로그램의 다섯 참가자에 의해 수행됩니다. 각 엔티티는 다음에서 설명하는 여러 API 및 기능을 구현하여 신뢰할 수 있는 방법으로 트랜잭션을 처리합니다.
- 트랜잭션 관리자는 트랜잭션 구분, 트랜잭션 자원 관리, 동기화 및 트랜잭션 컨텍스트 전파 지원에 필요한 서비스 및 관리 기능을 제공합니다.
- 응용 프로그램 서버는 트랜잭션 상태 관리 등의 응용 프로그램 런타임 환경 지원에 필요한 기반 구조를 제공합니다.
- 자원 관리자(자원 어댑터를 통한)는 응용 프로그램에게 자원에 대한 액세스를 제공합니다. 자원 관리자는 트랜잭션 관리자가 트랜잭션 연결, 트랜잭션 완료 및 복구 작업과 통신할 때 사용하는 트랜잭션 자원 인터페이스를 구현하여 분산된 트랜잭션에 참여합니다. 이런 자원 관리자의 예로 관계형 데이터베이스 서버를 들 수 있습니다.
- 자원 어댑터는 응용 프로그램 서버 또는 클라이언트가 자원 관리자와의 연결에 사용하는 시스템 수준 소프트웨어 라이브러리입니다. 자원 어댑터는 일반적으로 자원 관리자마다 따로 지정됩니다. 자원 어댑터는 라이브러리로 사용 가능하며 이것을 사용하는 클라이언트 주소 공간 내에서 사용됩니다. 이런 자원 어댑터의 예로는 JDBC 드라이버가 있습니다.
- J2EE 응용 프로그램 서버 환경에서 작업하기 위해 개발된 트랜잭션 사용자 응용 프로그램은 JNDI를 사용하여 트랜잭션 데이터 소스 및 선택적으로 트랜잭션 관리자를 조회합니다. EJB의 선언적 트랜잭션 속성 설정 또는 명시적인 프로그램형 트랜잭션 구분을 사용할 수 있습니다.
자원 관리자와 자원 어댑터 엔티티는 서로 밀접하게 연관되어 있어서, 자원 관리자라는 용어가 자원 어댑터와 혼용되는 경우도 많습니다.
트랜잭션 자원 관리자
다음 트랜잭션 자원 관리자는 J2EE 트랜잭션 내에서 지원됩니다.
데이터베이스
가장 자주 접하게 되는 J2EE 응용 프로그램의 트랜잭션 자원 관리자는 데이터베이스입니다. JDBC는 J2EE 구성 요소가 데이터베이스 액세스에 사용하는 API입니다. 데이터베이스 자원은 JDBC 자원으로 구성됩니다. JDBC 자원은 자원 관리자 또는 JDBC 드라이버가 관리합니다. JDBC 드라이버는 로컬 트랜잭션 또는 전역 트랜잭션 및 때로 로컬 및 전역 트랜잭션 모두에 대한 지원을 제공할 수 있습니다.
Sun ONE Application Server는 여러 J2EE 구성 요소의 JDBC 및 트랜잭션 사용을 지원합니다. JDBC 자원의 등록 및 구성 방법에 대한 자세한 내용은 "JDBC 자원 정보"를 참조하십시오. 응용 프로그램 서버는 트랜잭션 연속성 제공(즉 여러 응용 프로그램 구성 요소로부터 트랜잭션 초기화 및 데이터베이스 액세스 수행)을 담당합니다. 예를 들어, 서블릿이 트랜잭션을 시작하고, 데이터베이스를 액세스하고, 동일한 트랜잭션의 일부로 동일한 데이터베이스를 액세스하는 Enterprise Bean을 불러낸 후, 마지막으로 트랜잭션을 완결할 수 있습니다.
JMS 공급자
JMS는 Java Message Service의 약자입니다. JMS 공급자는 메시지 브로커 서비스를 의미하는 J2EE 용어입니다. JMS API는 응용 프로그램 사이에 신뢰할 수 있는 트랜잭션 방식의 교환을 제공합니다. 트랜잭션 JMS 데이터 소스 지원은 J2EE의 필수 기능입니다. JMS 자원 및 JDBC 자원이 함께 동일한 트랜잭션에 사용될 수 있습니다.
Sun ONE Application Server는 Sun ONE 메시지 대기열, 완전한 기능의 JMS 공급자 및 해당 트랜잭션 자원 관리자에 통합됩니다. 이렇게 하면 Sun ONE Application Server가 서블릿, JSP 페이지 및 Enterprise Bean에서 트랜잭션 JMS에 액세스할 수 있습니다. Sun ONE Application Server에 타사 JMS 공급자를 사용할 수도 있습니다. 자세한 내용은 "JMS 서비스 사용"을 참조하십시오.
J2EE 커넥터
Sun ONE Application Server는 트랜잭션 자원 관리자로 XATransaction 모드를 사용하는 자원 어댑터를 지원합니다. 플랫폼에서는 서블릿, JSP 페이지 및 Enterprise Bean에서 자원 어댑터로 트랜잭션 액세스할 수 있어야 합니다. 단일 트랜잭션 내의 여러 응용 프로그램 구성 요소에서 자원 어댑터에 액세스할 수 있습니다. 예를 들어, 서블릿이 트랜잭션을 시작하고, 자원 어댑터를 액세스하고, 동일한 트랜잭션의 일부로 자원 어댑터를 액세스하는 Enterprise Bean을 불러낸 후, 마지막으로 트랜잭션을 완결할 수 있습니다.
로컬 및 분산 트랜잭션
한 자원과만 관련 있는 트랜잭션은 로컬 트랜잭션을 사용하여 완료될 수 있습니다. 또한 로컬 트랜잭션은 모든 참여 응용 프로그램 구성 요소가 하나의 프로세스 내에서 실행되어야 합니다. 두 개 이상의 자원 또는 여러 참여 프로세스가 관련된 트랜잭션은 분산 또는 전역 트랜잭션이 될 수 있습니다. 로컬 트랜잭션 최적화는 최적화 전용 자원 관리자를 사용하며, 이것은 J2EE 응용 프로그램에 투명합니다.
트랜잭션 유형은 관련 자원 관리자에 구현된 인터페이스로 판단할 수 있습니다. 예를 들어, javax.sql.DataSource 인터페이스를 구현하는 JDBC 데이터 소스는 로컬 트랜잭션에 참여할 수 있습니다. javax.sql.XADataSource를 구현하는 데이터 소스는 전역 트랜잭션의 일부를 취할 수 있습니다. 일부 JDBC 자원은 두 인터페이스를 모두 구현하며, 이런 JDBC 자원이 Sun ONE Application Server에 등록되어 있으면 Sun ONE Application Server의 구성에 해당 자원의 선호 기능을 표시하는 구성 정보를 추가해야 할 수 있습니다.
로컬 트랜잭션이 더 간단하며 기본적으로 전역 트랜잭션보다 효율적입니다. 변형해야 할 데이터가 여러 데이터 소스에 있을 경우에는 로컬 트랜잭션이 적절하지 않습니다. 때로 몇 개의 데이터 소스가 트랜잭션에 나열되어야 하는지 예측할 수 없는 경우도 있습니다. 이 때문에 실제로는 전역 트랜잭션을 더 많이 사용합니다. 전역 트랜잭션에 사용할 수 있는 몇 가지 성능 개선 최적화가 있습니다.
J2EE는 트랜잭션 내의 여러 Enterprise Bean에 액세스하는 서블릿이나 JSP의 임의 조합을 모두 포함하는 트랜잭션 응용 프로그램을 지원합니다. 각 구성 요소는 하나 이상의 트랜잭션 자원 관리자에 대해 하나 이상의 연결을 가질 수 있습니다. 다음 그림에서, 호출 트리는 여러 Enterprise Bean을 액세스하는 서블릿 또는 JSP에서 시작하며, 이후 다른 Enterprise Bean을 액세스할 수 있습니다. 구성 요소는 연결을 통해 자원 관리자에 액세스합니다.
트랜잭션의 자원에 액세스하는 J2EE 구성 요소
예를 들어, 응용 프로그램은 위 그림의 모든 구성 요소가 단일 트랜잭션의 일부로 자원에 액세스해야 할 수도 있습니다. 응용 프로그램 서버 공급자는 이런 시나리오를 지원하는 트랜잭션 기능을 제공해야 합니다.
J2EE 트랜잭션 관리는 플랫 트랜잭션을 지원합니다. 플랫 트랜잭션은 자식(중첩된) 트랜잭션을 가질 수 없습니다.
트랜잭션 복구는 분산 트랜잭션에 있어 중요한 측면입니다. 크리티컬 포인트 동안 자원을 사용할 수 없거나 기타 복구할 수 없는 오류가 발생하면, 분산 트랜잭션의 상태를 모르게 될 수 있습니다. 꼬이거나 완료되지 못한 트랜잭션을 자동 및 수동으로 복구하는 것은 Sun ONE Application Server의 중요한 기능입니다. 자동 트랜잭션 복구는 관리 인터페이스를 사용하여 수행할 수 있습니다. 트랜잭션 복구 제어 방법의 자세한 내용은 "트랜잭션 서비스 관리"를 참조하십시오.
연결(여기에서는 자원과 동의어로 사용됨)은 공유 가능 여부가 표시될 수 있습니다. 공유 불가능한 방법으로 연결을 사용하려는 J2EE 응용 프로그램 구성 요소는 영향을 받는 측에 배포 정보를 제공하여 컨테이너가 연결을 공유하지 못하도록 해야 합니다. 이것이 필요할 수 있는 경우의 예로는 보안 속성, 고립화 수준, 문자 집합 및 로컬화 구성을 변경하는 경우가 포함됩니다.
컨테이너는 공유 불가능으로 표시된 연결을 공유하지 말아야 합니다. 연결이 공유 불가능으로 표시되어 있지 않으면, 이것은 연결이 실제 공유되어 있는지 여부와 상관없이 응용 프로그램에 투명해야 합니다.
J2EE 응용 프로그램 구성 요소는 선택적 전개 설명자 요소 res-sharing-scope를 사용하여 자원 관리자에 대한 연결의 공유 가능 여부를 표시할 수 있습니다. 컨테이너는 전개 관련 정보가 제공되지 않으면 공유 가능한 연결이라고 간주합니다. J2EE 응용 프로그램 구성 요소는 연결 객체를 캐시하여 여러 트랜잭션에서 다시 사용할 수 있습니다. 공유 연결을 제공하는 컨테이너는 이런 캐시된 연결 객체를 투명하게 전환하여(디스패치할 때) 올바른 트랜잭션 범위를 가진 적절한 공유 연결을 가리키도록 해야 합니다.
Enterprise Bean 응용 프로그램을 설계하는 경우, 개발자는 경계 지정 방법을 결정해야 합니다.
컨테이너 관리 트랜잭션
컨테이너 관리 트랜잭션이 있는 Enterprise Bean의 경우에는 EJB 컨테이너가 트랜잭션 경계를 설정합니다. Enterprise Bean 유형으로 Session, Entity 또는 Message-Driven을 가진 컨테이너 관리 트랜잭션을 사용할 수 있습니다. 컨테이너 관리 트랜잭션은 Enterprise Bean 코드가 트랜잭션의 경계를 명시적으로 표시하지 않기 때문에 간단하게 배포할 수 있습니다. 이 코드에는 트랜잭션 시작 및 종료 명령이 없습니다.
일반적으로 컨테이너는 Enterprise Bean 메소드가 시작하기 직전에 트랜잭션을 시작하고, 메소드가 종료되기 직전 트랜잭션을 완결합니다. 각 메소드는 단일 트랜잭션에 관련될 수 있습니다. 한 메소드 내에 중첩된 트랜잭션 또는 여러 트랜잭션을 허용하지 않습니다.
컨테이너 관리 트랜잭션이 트랜잭션에 연결될 때 모든 메소드가 필요하지는 않습니다. Bean을 배포할 때에는 트랜잭션 속성을 설정하여 트랜잭션과 관련된 Bean의 메소드를 지정합니다.
이 절에서는 다음 내용을 설명합니다.
트랜잭션 속성
트랜잭션 속성은 트랜잭션 범위를 제어합니다. 다음 그림은 범위 제어가 왜 중요한지 보여주고 있습니다. 다이어그램에서, 메소드 A는 트랜잭션을 시작하고 Bean 2의 메소드 B는 트랜잭션을 불러냅니다. 메소드 B가 실행되면 메소드 A가 시작한 트랜잭션 범위 내에서 실행될까요? 아니면 새 트랜잭션으로 실행될까요? 답은 메소드 B의 트랜잭션 속성에 따라 달라집니다.
트랜잭션 속성트랜잭션 속성은 다음 값 중 하나를 가질 수 있습니다.
Required
클라이언트가 트랜잭션 내에서 실행 중일 때 Enterprise Bean의 메소드를 불러내면, 이 메소드는 클라이언트 트랜잭션 내에서 실행됩니다. 클라이언트가 트랜잭션과 관련되어 있지 않으면, 메소드가 실행되기 전 먼저 컨테이너가 새 트랜잭션을 시작합니다.
Required 속성은 대부분의 트랜잭션에 사용됩니다. 이 때문에 최소한 개발 초기에는 이것을 기본값으로 사용하는 것이 좋습니다. 트랜잭션 속성은 선언적이기 때문에 나중에 쉽게 변경할 수 있습니다.
RequiresNew
클라이언트가 트랜잭션 내에서 실행 중일 때 Enterprise Bean의 메소드를 불러내면, 컨테이너는 다음 단계를 수행합니다.
클라이언트가 트랜잭션과 관련되어 있지 않으면, 메소드가 실행되기 전 먼저 컨테이너가 새 트랜잭션을 시작합니다.
메소드가 새 트랜잭션 내에서 항상 실행되도록 하려면 RequiresNew 속성을 사용해야 합니다.
Mandatory
클라이언트가 트랜잭션 내에서 실행 중일 때 Enterprise Bean의 메소드를 불러내면, 이 메소드는 클라이언트 트랜잭션 내에서 실행됩니다. 클라이언트가 트랜잭션과 관련되어 있지 않으면 TransactionRequiredException이 발생합니다.
Enterprise Bean의 메소드가 클라이언트 트랜잭션을 사용해야 하는 경우 Mandatory 속성을 사용합니다.
NotSupported
클라이언트가 트랜잭션 내에서 실행 중일 때 Enterprise Bean의 메소드를 불러내면, 컨테이너는 이 메소드를 불러내기 전 먼저 클라이언트 트랜잭션을 일시 중단합니다. 메소드가 완료된 다음 컨테이너는 클라이언트 트랜잭션을 다시 시작합니다.
클라이언트가 트랜잭션과 관련되어 있지 않으면, 컨테이너는 메소드가 실행되기 전 새 트랜잭션을 시작하지 않습니다.
트랜잭션이 필요하지 않은 메소드에는 NotSupported 속성을 사용합니다. 트랜잭션 불러내기는 오버헤드가 있기 때문에 이 속성은 성능을 개선할 수 있습니다.
Supports
클라이언트가 트랜잭션 내에서 실행 중일 때 Enterprise Bean의 메소드를 불러내면, 이 메소드는 클라이언트 트랜잭션 내에서 실행됩니다. 클라이언트가 트랜잭션과 관련되어 있지 않으면, 컨테이너는 메소드가 실행되기 전 새 트랜잭션을 시작하지 않습니다.
메소드의 트랜잭션 작업은 다양하기 때문에 Supports 속성은 주의해서 사용해야 합니다.
Never
클라이언트가 트랜잭션 내에서 실행 중일 때 Enterprise Bean의 메소드를 불러내면, 컨테이너는 RemoteException를 발생합니다. 클라이언트가 트랜잭션과 관련되어 있지 않으면, 컨테이너는 메소드가 실행되기 전 새 트랜잭션을 시작하지 않습니다.
속성 요약
다음 표는 트랜잭션 속성의 영향을 요약합니다. T1 및 T2 트랜잭션은 모두 컨테이너로 제어됩니다. T1 트랜잭션은 Enterprise Bean의 메소드를 호출하는 클라이언트와 관련되어 있습니다. 대부분의 경우 클라이언트도 별도의 Enterprise Bean입니다. T2 트랜잭션은 메소드가 실행되기 전 컨테이너에 의해 시작됩니다.
마지말 열의 '없음'이라는 단어는 비즈니스 메소드가 컨테이너가 제어하는 트랜잭션 내에서 실행되지 않음을 표시합니다. 하지만 이런 비즈니스 메소드에 호출된 데이터베이스는 DBMS의 트랜잭션 관리자가 제어할 수 있습니다.
트랜잭션 속성
트랜잭션 속성
클라이언트 트랜잭션
비즈니스 메소드의 트랜잭션
Required
없음
T2
T1
T1
RequiresNew
없음
T2
T1
T2
Mandatory
없음
오류
T1
T1
NotSupported
없음
없음
T1
없음
Supports
없음
T1
없음
T1
트랜잭션 속성 설정
트랜잭션 속성은 배포 설명자에 저장되기 때문에 Enterprise Bean 작성, 응용 프로그램 어셈블리 및 배포 등 J2EE 응용 프로그램 전개자의 여러 단계 도중 변경될 수 있습니다. 하지만 Bean 작성시 속성을 지정하는 것은 개발자가 해야 합니다. 속성은 구성 요소를 더 큰 응용 프로그램으로 어셈블리하는 응용 프로그램 개발자만 수정할 수 있어야 합니다. J2EE 응용 프로그램을 배포하는 사람은 트랜잭션 속성을 지정할 책임이 없습니다.
전체 Enterprise Bean 또는 각 메소드에 대해 트랜잭션 속성을 지정할 수 있습니다. 한 속성은 메소드에 대해 지정하고 다른 속성은 Bean에 대해 지정한 경우에는 메소드에 대해 지정한 속성이 우선권을 갖습니다. 각 메소드에 대해 속성을 지정하는 경우 필요한 사항은 Bean 유형에 따라 달라집니다. Session Bean에는 비즈니스 메소드에 정의된 속성이 필요하지만, 생성 메소드에 대해서는 허용하지 않습니다. Entity Bean에는 비즈니스, 생성, 제거 및 검색 메소드에 대한 트랜잭션 속성이 필요합니다. Message-Driven Bean에는 onMessage 메소드에 대한 트랜잭션 속성(Required 또는 NotSupported 중 하나)이 필요합니다.
컨테이너 관리 트랜잭션 롤백
컨테이너 관리 트랜잭션의 롤백에는 두 가지 방법이 있습니다. 먼저 시스템 예외가 발생하면 컨테이너는 자동으로 트랜잭션을 롤백합니다. 두 번째로 EJBContext 인터페이스의 setRollbackOnly 메소드를 불러내서, Bean 메소드가 컨테이너에게 트랜잭션 롤백을 지시할 수 있습니다. Bean이 응용 프로그램 예외를 발생시키면 롤백이 자동으로 실행되지 않아도 setRollbackOnly를 호출하여 초기화할 수 있습니다.
다음 예에서 BankEJB 예의 transferToSaving 메소드는 setRollbackOnly 메소드를 나타내고 있습니다. 수표 계정의 잔액이 마이너스가 되면, transferToSaving은 setRollBackOnly를 불러내고 응용 프로그램 예외(InsufficientBalanceException)를 발생시킵니다. updateChecking 및 updateSaving 메소드는 데이터베이스 테이블을 업데이트합니다. 업데이트에 실패하면 메소드는 SQLException을 발생시키고 transferToSaving 메소드는 EJBException을 발생시킵니다.
EJBException은 시스템 예외기 때문에, 컨테이너는 자동으로 트랜잭션을 롤백합니다. 다음은 transferToSaving 메소드의 코드입니다.
public void transferToSaving(double amount) throws
InsufficientBalanceException {
checkingBalance -= amount;
savingBalance += amount;if (checkingBalance < 0.00) {
context.setRollbackOnly();throw new InsufficientBalanceException();
}
try {
updateChecking(checkingBalance);updateSaving(savingBalance);
} catch (SQLException ex) {
throw new EJBException
("Transaction failed due to SQLException: "
+ ex.getMessage());
}
}컨테이너가 트랜잭션을 롤백하는 경우, 이것은 항상 트랜잭션 내의 SQL 호출로 발생한 데이터 변경을 모두 실행 취소합니다. 하지만 컨테이너는 Entity Bean에서만 인스턴스 변수에 대한 변경을 취소합니다(이 작업은 Entity Bean의 ejbLoad 메소드를 자동으로 호출하여 수행하며, 데이터베이스에서 인스턴스 변수가 로드됨). 롤백이 발생하면 Session Bean은 트랜잭션 내에 변경된 인스턴스 변수를 명시적으로 다시 설정합니다. Session Bean 인스턴스 변수를 다시 설정하는 가장 쉬운 방법은 SessionSynchronization 인터페이스를 구현하는 것입니다.
트랜잭션 ID를 명령줄 인터페이스를 통해 전달하여 트랜잭션을 롤백할 수도 있습니다. 자세한 내용은 "명령줄 인터페이스를 사용한 트랜잭션 관리"를 참조하십시오.
Session Bean의 인스턴스 변수 동기화
SessionSynchronization 인스턴스(선택적)를 사용하면 인스턴스 변수를 데이터베이스 내의 대응하는 값과 동기화할 수 있습니다. 컨테이너는 트랜잭션의 각 주요 단계에서 SessionSynchronization 메소드(afterBegin, beforeCompletion 및 afterCompletion)를 불러냅니다.
afterBegin 메소드는 새 트랜잭션이 시작되었음을 인스턴스에게 알립니다. 컨테이너는 처음으로 트랜잭션 내의 비즈니스 메소드를 불러내기 전에 먼저 afterBegin을 불러냅니다. afterBegin 메소드는 데이터베이스에서 인스턴스 변수를 로드하기에 좋은 위치입니다. 예를 들어, BankBean 클래스는 afterBegin 메소드 내에 checkingBalance 및 savingBalance 변수를 로드합니다.
public void afterBegin() {
System.out.println("afterBegin()");
try {
checkingBalance = selectChecking();
savingBalance = selectSaving();
} catch (SQLException ex) {
throw new EJBException("afterBegin Exception: " +
ex.getMessage());
}
}컨테이너는 비즈니스 메소드는 완료되었지만 트랜잭션이 완결되기 전에 beforeCompletion 메소드를 불러냅니다. beforeCompletion 메소드는 Session Bean이 트랜잭션을 롤백할 수 있는(setRollbackOnly를 호출하여) 마지막 장소입니다. 아직 인스턴스의 변수 값을 데이터베이스에 업데이트하지 않았다면, Session Bean은 이 작업을 beforeCompletion 메소드에서 수행합니다.
afterCompletion 메소드는 트랜잭션이 완료되었음을 표시합니다. 여기에는 boolean 값의 매개 변수 하나가 있으며, 트랜잭션이 완결되면 true, 트랜잭션이 롤백되면 false 값을 갖습니다. 롤백이 발생하면 Session Bean은 afterCompletion 메소드에서 데이터베이스의 인스턴스 변수를 새로 고칠 수 있습니다.
public void afterCompletion(boolean committed) {
System.out.println("afterCompletion: " + committed);
if (committed == false) {
try {
checkingBalance = selectChecking();
savingBalance = selectSaving();
} catch (SQLException ex) {
throw new EJBException("afterCompletion SQLException:
" + ex.getMessage());
}
}
}컨테이너 관리 트랜잭션에 허용되지 않는 메소드
컨테이너가 설정한 트랜잭션 경계를 간섭할 수 있는 메소드는 모두 불러낼 수 없습니다. 금지되는 메소드 목록은 다음과 같습니다.
- java.sql.Connection의 완결, setAutoCommit 및 롤백 메소드.
- javax.ejb.EJBContext의 getUserTransaction 메소드.
- javax.transaction.UserTransaction의 모든 메소드.
하지만 Bean 관리 트랜잭션에는 이 메소드들을 사용하여 경계를 설정할 수 있습니다.
Bean 관리 트랜잭션
Bean 관리 트랜잭션의 경우, Session 또는 Message-Driven Bean 내의 코드에서 명시적으로 트랜잭션 경계를 표시합니다. Entity Bean은 Bean 관리 트랜잭션을 가질 수 없으며 대신 컨테이너 관리 트랜잭션을 사용해야 합니다. 컨테이너 관리 트랜잭션을 가진 Bean은 필요한 코드가 줄어들지만 한 가지 제한을 갖습니다. 메소드가 실행되면 Bean은 단일 트랜잭션에 관련되거나 아무런 트랜잭션에도 관련되지 않을 수 있습니다. 이 제한 때문에 Bean 코딩이 어려워지는 경우, Bean 관리 트랜잭션 사용을 고려해야 합니다.
다음 의사 코드는 Bean 관리 트랜잭션으로 구할 수 있는 세분화된 제어 종류를 표시합니다. 의사 코드는 여러 조건을 확인하여 비즈니스 메소드 내에서 여러 트랜잭션의 시작 또는 중지 여부를 결정합니다.
begin transaction
...
update table-a
...
if (condition-x)
commit transaction
else if (condition-y)
update table-b
commit transaction
else
rollback transaction
begin transaction
update table-c
commit transaction트랜잭션 서비스 관리
관리 인터페이스 또는 명령줄 인터페이스를 사용하여 트랜잭션을 관리할 수 있습니다.
이 절에는 다음 주제가 포함됩니다.
관리 인터페이스를 사용한 트랜잭션 관리
관리 인터페이스를 사용하여 트랜잭션 모니터링, 로그 수준 설정, 고급 옵션 지정 등을 수행할 수 있습니다.
복구 정책 및 시간 초과와 같은 인스턴스 범위의 트랜잭션 서비스 속성을 제어할 수 있습니다. 여기에서 지정하는 등록 정보 및 구성은 server.xml 파일에 저장됩니다.
트랜잭션 서비스 옵션을 구성하려면 다음 작업을 수행합니다.
- 관리 인터페이스의 왼쪽 창에서 트랜잭션 구성을 수정할 Sun ONE Application Server 인스턴스 트리를 엽니다.
- 배포된 J2EE 서비스에서 트랜잭션 서비스를 선택합니다. 관리 인터페이스 오른쪽 창의 그림 트랜잭션 서비스 구성 옵션에 표시된 다음 창이 나타납니다.
트랜잭션 서비스 구성 옵션
Java Transaction Service의 모니터링 가능한 속성
- "로그 수준" 드롭다운 목록에서 트랜잭션에 설정할 로그 수준을 선택합니다. 로그 수준 및 통합 방법의 자세한 내용은 "로깅 사용"을 참조하십시오.
- 서버 재시작시 실패한 트랜잭션을 자동으로 복구하려면 "재시작시 복구" 확인란을 표시합니다. 트랜잭션 완결 프로토콜의 크리티컬 포인트 동안 자원을 사용할 수 없으면, 트랜잭션은 완료되지 못하고 트랜잭션 로그 파일에 남을 수 있습니다. 이 확인란이 표시되어 있으면 서버는 서버 재시작시 오류가 발생한 트랜잭션 복구를 시도합니다. 관련 자원에 여전히 접근할 수 없으면 서버 재시작 시간이 지연될 수 있습니다. 이 확인란은 기본적으로 표시되지 않습니다.
- 컨테이너 관리 트랜잭션이 있는 Enterprise Bean의 경우, 트랜잭션 시간 초과(초) 등록 정보의 값을 설정하여 트랜잭션 시간 초과 간격을 제어할 수 있습니다.
이 등록 정보의 값이 0으로 설정되면 트랜잭션은 시간 초과되지 않습니다.
"트랜잭션 시간 초과(초)" 필드에 트랜잭션 시간 초과 간격을 지정합니다. 트랜잭션이 지정된 시간 내에 완료되지 않으면 트랜잭션은 롤백됩니다. 이 속성의 값이 0으로 설정되면 트랜잭션은 시간 초과되지 않습니다.
- "트랜잭션 로그 위치" 필드에 로그 파일을 저장할 디렉토리의 절대 경로를 지정합니다. 새로 지정한 트랜잭션 로그 디렉토리를 적용하려면 서버를 재시작해야 합니다.
- "발견적 결정" 드롭다운 상자에서 트랜잭션에 적용할 발견적 결정을 선택합니다. 명백한 결과를 결정할 수 없는 경우 표시된 옵션에서 완결 또는 롤백을 선택하여 응용 프로그램 서버에서 복구 도중 의심스러운 트랜잭션의 결과를 결정하는 방법을 지정합니다. 발견적 결정을 롤백으로 설정하면 트랜잭션을 롤백합니다. 이런 트랜잭션을 완결하는 것이 허용되는 경우도 있습니다.
- "키 포인트 간격(트랜잭션)" 필드에 로그의 키 포인트 작업 사이의 트랜잭션 개수를 지정합니다. 키 포인트 작업은 완료된 트랜잭션의 항목을 제거하고 파일을 압축하여 트랜잭션 로그 파일의 크기를 줄입니다. 이 속성 값이 커지면 트랜잭션 로그 파일이 커지지만, 키 포인트 작업이 줄어들어 성능이 좋아질 수 있습니다. 이 값이 작아지면(예를 들어, 100) 로그 파일이 작아지지만, 키 포인트 작업 빈도가 높아져서 성능이 약간 낮아질 수 있습니다.
명령줄 인터페이스를 사용한 트랜잭션 관리
다음 절에서 설명한 것처럼, CLI (Command Line Interface)를 사용하여 데이터베이스 트랜잭션을 관리 및 모니터링할 수 있습니다.
이 절은 명령줄 인터페이스를 사용한 트랜잭션 관리 및 모니터링 방법을 설명합니다.
실행 중인 트랜잭션 나열
다음 명령은 실행 중인 트랜잭션 데이터를 구할 때 사용됩니다(multimode에 있고 이미 사용자 이름 및 암호를 설정했다고 가정합니다).
- asadmin> get --monitor
<instanceName>.transaction-service.inflight-tx다중 행 출력은 다음과 같습니다.
Transaction Id State Elapsed Time (ms)
txnid1 Prepared 20
txnid2 Active 100
txnid3 Active 120
... ... ...
트랜잭션 관리
실행 중인 트랜잭션 나열의 예에서는 트랜잭션 ID txn-ids, txnid2 및 txnid3로 트랜잭션을 롤백한다고 가정합니다. 선택한 트랜잭션을 롤백하는 샘플 명령은 다음의 예와 같습니다.
asadmin> set --monitor <instanceName>.transaction-service.rollback-list=txnid2,txnid3
트랜잭션 서비스 고정
트랜잭션 서비스를 고정하려면 다음 명령을 실행합니다.
asadmin> set --monitor <instanceName>.transaction-service.freeze=true
트랜잭션 서비스가 고정되면 응용 프로그램 서비스 내의 트랜잭션 관리자는 모든 실행 중인 트랜잭션이 일시 중단됩니다. 고정은 제품 배포 시스템에서는 권장하지 않습니다.
트랜잭션 서비스를 고정 해제하려면 다음 명령을 실행합니다.
asadmin> set --monitor <instanceName>.transaction-service.freeze=false
트랜잭션 서비스가 다시 동작 중으로 설정되면 시스템은 중단되었던 지점부터 다시 계속합니다. 활성 시스템을 너무 오래 고정 상태로 두면 일부 데이터베이스 연결이 시간 초과되어 트랜잭션이 롤백될 수 있습니다.
트랜잭션 모니터링
실행 중인 트랜잭션 데이터를 포함하여 트랜잭션 데이터를 모니터링하려면 다음 명령을 실행합니다.
asadmin> get --monitor <instanceName>.transaction-service.*
명령을 실행했을 때 활성 트랜잭션이 없으면 다음 출력을 구할 수 있습니다.
total-tx-completed = 5
total-tx-rolledback = 2
total-tx-inflight = 0
isFrozen = false
tx-inflight = No active transactions found.
명령을 실행했을 때 활성 트랜잭션이 있으면 다음 출력을 구할 수 있습니다.
total-tx-completed = 5
total-tx-rolledback = 2
total-tx-inflight = 2
isFrozen = false
tx-inflight =
Transaction Id State Elapsed Time(ms)
txnid1 Prepared 500
txnid2 Active 360
출처 - https://docs.oracle.com/cd/E19957-01/816-6865-10/agjts.html#266545