EntityManager
인터페이스를 도입한 것입니다. 지속성 엔터티 ID에 대해 고유한 엔터티 인스턴스가 존재하는, 관리 엔터티 인스턴스의 집합. 지속성 컨텍스트 내부에서 엔터티 인스턴스와 그 수명 주기는 엔터티 관리자에 의해 관리된다.
또한 자바 지속성 아키텍처에 따르면, 컨테이너 관리 지속성 컨텍스트, 즉 수명 주기가 컨테이너에 의해 자동 관리되는
지속성 컨텍스트는 단일 트랜잭션 범위의 수명 또는 여러 트랜잭션을 포괄하는 확장된 수명을 갖도록 정의할 수 있습니다. 수명의
범위는 엔터티 관리자 생성 시 PersistenceContextType
클래스에 지정된 유형에 따라 결정됩니다.
단일 트랜잭션을 범위로 하는 컨테이너 관리 지속성 컨텍스트의 경우, 연결된 트랜잭션이 커밋하거나 JTA(Java Transaction API)를 통해 롤백될 때 지속성 컨텍스트가 종료합니다. 그에 비해 확장된 수명을 갖는 컨테이너 관리 지속성 컨텍스트는 상태 유지 세션 빈이 생성될 때 시작하고, 상태 유지 세션 빈이 컨테이너에서 제거될 때만 종료합니다. 확장 지속성 컨텍스트는 상태 유지 세션 빈에 바인딩되었다고 말합니다. 상태 유지 세션 빈은 컨테이너에서 관리하는 확장 엔터티 관리자를 가질 수 있습니다.
트랜잭션 범위 지속성 컨텍스트와 확장 지속성 컨텍스트의 중요한 차이점 중 하나는 트랜잭션 완료 후 엔터티의 상태입니다.
트랜잭션 범위 지속성 컨텍스트의 경우 엔터티는 분리됩니다. 즉 더 이상 관리되지 않습니다. 확장 지속성 컨텍스트의 경우
엔터티는 계속 관리됩니다. 다시 말해, persist
와 같이 트랜잭션의 외부에서 수행되는 모든 작업이
대기열에 있다가 지속성 컨텍스트가 트랜잭션에 연결될 때 (그리고 커밋될 때) 커밋됩니다. 따라서 확장 지속성 컨텍스트는 여러
상호 작용을 포괄하는 사용자 대화를 모델링할 때 적합합니다. 사용자 대화 전체를 포괄하는 빈 관리 트랜잭션을 사용해도 똑같은
효과를 얻을 수 있습니다. UserTransaction.begin()
메소드를 사용하여 이 트랜잭션을 시작합니다. 그러나 이 대안은 확장 지속성 컨텍스트를 활용하는 것보다 더 복잡합니다.
이 테크팁에서는 확장 지속성 컨텍스트와 함께 상태 유지 세션 빈과 엔터티 관리자를 사용하는 애플리케이션을 소개합니다. 이 애플리케이션에서는 여행 예약을 처리합니다. 사용자가 여행을 위해 항공편과 렌터카를 예약할 수 있습니다. 이 팁에는 샘플 패키지가 제공됩니다. 이 팁의 코드 예제는 해당 패키지에 포함된 샘플의 소스 코드에서 따온 것입니다.
여행 예약 애플리케이션
이 팁의 애플리케이션에서는 사용자가 여행을 예약할 수 있는 간단한 웹 페이지를 제시합니다.
애플리케이션의 소스 코드를 살펴보면, ControllerServlet
서블릿이 예약 웹 페이지를 제시합니다. 이 서블릿은 상태 유지 세션 빈 BookingControllerLocalBean
을 사용하여 애플리케이션의 대화 상태를 유지합니다. 상태 유지 세션 빈에서는 엔터티 관리를 위해 컨테이너 관리 확장 지속성 컨텍스트를 사용합니다. 애플리케이션에서 confirmBooking()
을 제외한 모든 메소드의 기본 트랜잭션 속성이 NOT_SUPPORTED입니다.
다음 BookingControllerLocalBean
코드에서는 컨테이너 관리 확장 지속성 범위를 삽입합니다.
@PersistenceContext(type=PersistenceContextType.EXTENDED)
private EntityManager em;
여행 예약 시작
서블릿은 BookingControllerLocalBean
에서 startBooking()
메소드를 호출하여 여행 예약 프로세스를 시작합니다. 서블릿에서의 메소드 호출은 다음과 같습니다.
bookingController = (BookingControllerLocal) (new InitialContext()).lookup("java:comp/env/ejb/BookingController");
session.setAttribute("bc", bookingController);
tripId = bookingController.startBooking();
그리고 BookingControllerLocalBean
의 startBooking()
메소드입니다.
public Trip startBooking() {
this.trip = new Trip(); // Create a new Trip
em.persist(trip);
return trip(); //Return the Trip which is an Entity
}
다시 말하자면, 이 애플리케이션에서는 확장 지속성 컨텍스트를 사용하므로, 트랜잭션 없이 메소드가 호출되더라도 Trip
엔터티는 계속 관리됩니다.
항공편 및 차량 예약 처리
사용자가 항공편이나 차량 예약을 요청하면 서블릿은 BookingControllerLocalBean
의 doBooking(Booking b)
메소드를 호출합니다. 이 메소드는 엔터티를 지속성으로 만들기 위해 em.persist
메소드를 호출합니다. 그러면 이 메소드는 다음과 같이 Trip
엔터티에 Booking
엔터티를 추가합니다.
trip.getBookings().add(b);
b.setTrip(trip);
트랜잭션 내부에서 doBooking()
메소드가 호출되지 않습니다. 그 때문에 엔터티는 데이터베이스로 플러시되지 않고, 계속 엔터티 관리자에 의해 관리됩니다. 따라서 doBooking()
메소드가 호출된 후에도 Booking
객체를 수정할 수 있습니다. 한편 이 애플리케이션이 트랜잭션 범위의 엔터티 관리자를 사용할 경우 엔터티 관리자가 다시 엔터티를 관리하게 하려면 다음 트랜잭션이 시작할 때 em.merge()
를 호출해야 합니다. 하지만 애플리케이션에서는 확장 지속성 범위의 엔터티 관리자를 사용하므로, 이 엔터티는 트랜잭션 커밋 후에도 계속 관리됩니다.
다음은 doCarBooking()
메소드의 완성된 코드입니다.
public void doBooking(Booking b) {
em.persist(b);
trip.getBookings().add(b);
b.setTrip(trip);
}
여행 예약 상태 표시
서블릿은 BookingControllerLocalBean
의 getAllBooking()
메소드를 호출하여 여행의 모든 Booking
엔터티를 표시합니다. 이 메소드는 데이터베이스에서 데이터를 가져오지 않습니다. 그 대신 Trip
엔터티 내부의 Booking
엔터티 컬렉션을 가져옵니다.
다음은 getAllBooking()
메소드의 코드입니다. .
public List<Booking>getAllBookings() {
return trip.getBookings();
}
여행 예약 완료
사용자가 Confirm 버튼을 클릭하면 서블릿은 BookingControllerLocalBean
의 confirmTrip()
메소드를 호출합니다. 이 메소드는 아무 작업도 수행하지 않습니다.
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void confirmTrip() {
em.flush();
}
그러나 메소드가 트랜잭션 내부에서 실행되므로 컨테이너는 확장된 지속성 관리자를 해당 트랜잭션과 자동으로 연결시킵니다. 메소드가 완료되면 컨테이너는 트랜잭션을 커밋하고 엔터티 관리자는 엔터티의 상태를 데이터베이스에 플러시합니다.
샘플 코드 실행하기
이 팁에는 샘플 패키지가 제공됩니다. 샘플을 설치하고 실행하려면 다음 단계를 수행합니다.
techtip3.ear
라는 이름의 엔터프라이즈 아카이브가 나타나야 합니다.
<glassfish_install_dir>/bin/asadmin start-domain
여기서 <glassfish_install_dir>
는 GlassFish v2를 설치한 디렉토리입니다.
<glassfish_install_dir>/bin/asadmin start-database
여기서 <glassfish_install_dir>
는 GlassFish v2를 설치한 디렉토리입니다.
techtip3.ear
를 배포합니다. 이 작업은 다양한 방법으로 수행할 수 있습니다. 그 중 하나는 명령줄에 다음 명령을 입력하는 것입니다. <glassfish_install_dir>/bin/asadmin deploy techtip3.ear
요약
이 팁에서는 사용자와의 여러 상호 작용을 포괄하는 긴 대화를 처리하기 위해 확장 지속성 컨텍스트와 함께 컨테이너 관리 엔터티 관리자를 사용하는 예를 소개했습니다. 또한 이 예제에서는 중간 사용자 상호 작용을 하나의 트랜잭션 내에서 처리할 필요가 없도 이러한 유형의 엔터티 관리자가 트랜잭션 완료 시 어떻게 플러시되는지 살펴봤습니다.
저자 정보