2장. 아키텍처

2.1. 개요

Hibernate 아키텍처에 대한 (매우) 높은 수준의 개요::

이 다이어그램은 어플리케이션에 영속화 서비스들(과 영속 객체들)을 제공하기 위해 데이터베이스와 컨피그레이션을 사용하는 Hibernate를 보여준다.

우리는 런타임 아키텍처에 대한 보다 상세한 뷰를 보여주고 싶다. 불행하게도, Hibernate는 유연하며 몇 가지 접근법들을 제공한다. 우리는 두 가지 극단을 보여줄 것이다. "경량급" 아키텍처는 그것 자신의 JDBC 커넥션들을 제공하고 그것 자신의 트랜잭션들을 관리하는 어플리케이션을 갖는다. 이 접근법은 Hibernate의 API의 최소 부분집합을 사용한다:

"전체 정수" 아키텍처는 기본 JDBC/JTA로부터 어플리케이션을 추상화 시키고 Hibernate로 하여금 상세한 것을 처리하게 한다.

다음은 다이어그램들 내에 있는 객체들에 대한 몇가지 정의들이다:

SessionFactory (org.hibernate.SessionFactory)

단일 데이터베이스에 대한 컴파일된 매핑들의 threadsafe (불변의) 캐시. Session과 ConnectionProvider의 클라이언트를 위한 팩토리. 프로세스 레벨 또는 클러스터 레벨에서 트랜잭션들 사이에 재사용 가능한 데이터의 선택적인 (second-level) 캐시를 보관할 수도 있다.

Session (org.hibernate.Session)

어플리케이션과 영속 저장소 사이의 대화를 표현하는 단일 쓰레드이고, 수명이 짧은 객체. JDBC 커넥션을 포장한다. Transaction 용 팩토리. 객체 그래프를 네비게이트 하거나 식별자로 객체들을 룩업할 때 사용되는 영속 객체들에 대한 필수적인(첫 번째 레벨의) 캐시를 보관한다.

영속 객체들과 콜렉션들

persistent 상태와 비지니스 기능을 포함하는 수명이 짧고, 단일 쓰레드인 객체들. 이것들은 통상의 JavaBeans/POJO들일 수 있고, 오직 그것들에 대한 오직 특별한 것은 그것들이 현재 (정확하게 한 개의) Session과 연관되어 있다는 점이다. Session이 닫히자마자, 그것들은 분리될(detached 상태가 될) 것이고 어플리케이션 레이어에서 사용하는 것이 자유로와진다(예를 들면. 직접적으로 프리젠테이션 계층으로 데이터 전송 객체들로서 그리고 직접적으로 프리젠테이션 계층으로부터 데이터 전송 객체들로서).

전이(Transient, 필자 주-과도) 객체들과 콜렉션들

Session과 현재 연관되어 있지 않은 영속 클래스들의 인스턴스들. 그것들은 어플리케이션에 의해 초기화 되었고 (아직) 영속화 되지 않았거나 그것들은 닫혀진Session에 의해 초기화 되었을 수도 있다.

Transaction (org.hibernate.Transaction)

(옵션) 작업의 원자 단위를 지정하기 위해 어플리케이션에 의해 사용되는 단일 쓰레드이고, 수명이 짧은 객체. 기본 JDBC, JTA 또는 CORBA 트랜잭션으로부터 어플리케이션을 추상화 시킨다. 몇몇 경우들에서 하나의 Session은 여러 개의 Transaction들에 걸칠 수 있다. 하지만 기본 API 또는 Transaction을 사용하는 트랜잭션 경계 설정은 결코 옵션이 아니다!

ConnectionProvider (org.hibernate.connection.ConnectionProvider)

(옵션) JDBC 커넥션들에 대한 팩토리(그리고 그것들의 pool). 기본 Datasource 또는 DriverManager로부터 어플리케이션을 추상화 시킨다. 어플리케이션에 노출되지는 않지만 개발자에 의해 확장/구현 된다.

TransactionFactory (org.hibernate.TransactionFactory)

(옵션) Transaction 인스턴스들에 대한 팩토리. 어플리케이션에 노출되지는 않지만 개발자에 의해 확장/구현 된다.

Extension Interfaces

Hibernate는 당신의 영속 계층의 특성을 맞춤화 시키기 위해 당신이 구현할 수 있는 선택적인 확장 인터페이스들을 제공한다. 상세한 것은 API 문서를 보라.

주어진 "경량급" 아키텍처의 경우, 어플리케이션은 JTA 또는 JDBC와 직접 대화하기 위해서 Transaction/TransactionFactory 그리고/또는 ConnectionProvider API들을 무시한다.

2.2. 인스턴스 상태들

영속 클래스들의 인스턴스는 세개의 상태들 중 하나 일 수 있다. 그것들(상태들)은 영속 컨텍스트(persistence context)에 대해 정의된다. Hibernate Session 객체는 영속 컨텍스트이다:

transient

인스턴스는 임의의 컨텍스트와 연관되어 있지 않고, 결코 연관된 적이 없었다. 그것은 영속 식별자(프라이머리 키 값)을 갖지 않는다.

persistent

인스턴스는 현재 영속 컨텍스트와 연관되어 있다. 그것은 영속 식별자(프라이머리 키 값) 그리고 아마 데이터베이스 내에 있는 대응하는 행을 갖는다. 특별한 영속 컨텍스트의 경우, Hibernate는 영속 identity가 Java identity(객체의 메모리 내 위치)와 같다는 점을 보증한다.

detached

인스턴스는 영속 컨텍스트와 한번 연관되었지만, 그 컨텍스트가 닫혔거나, 그 인스턴스가 또 다른 프로세스로 직렬화 되었다. 그것은 영속 identity 그리고, 아마 데이터베이스 내에 대응하는 행을 갖는다. detached 인스턴스들의 경우, Hibernate는 영속 identity과 Java identity 사이의 관계를 보증하지 않는다.

2.3. JMX 통합

JMX는 자바 컴포넌트 관리를 위한 J2EE 표준이다. Hibernate는 JMX 표준 서비스를 통해 관리될 수도 있다. 우리는 배포본 내에 MBean 구현, org.hibernate.jmx.HibernateService를 제공한다.

JBoss 어플리케이션 서버 상에 Hibernae를 JMX 서비스로서 배치하는 방법에 대한 예제는 JBoss 사용자 가이드를 보길 바란다. JBoss 어플리케이션 서버 상에서, 만일 당신이 JMX를 사용하여 배치할 경우 당신은 또한 다음 이점들을 얻는다:

  • Session 관리: Hibernate Session의 생명주기가 JTA 트랜잭션의 영역 내에 자동적으로 바인드 될 수 있다. 이것은 당신이 더이상 Session을 수작업으로 열고 닫지 않아도 됨을 의미하고, 이것은 JBoss EJB 인터셉터의 업무가 된다. 당신은 또한 더 이상 당신의 코드 어느 곳에서든 트랜잭션 경계설정에 대해 걱정하지 않아도 된다(당신이 물론 이식성 있는 영속 계층을 작성하고자 원하지 않는한, 이를 위해 옵션 Hibernate Transaction API를 사용하라). 당신은 Session에 접근하기 위해 HibernateContext를 호출한다.

  • HAR 배치: 대개 당신은 JBoss 서비스 배치 디스크립터를 사용하여 Hibernate JMX 서비스를 (EAR 과/또는 SAR 파일로) 배치하고, 그것은 Hibernate SessionFactory의 통상적인 구성 옵션들 모두를 지원한다. 하지만 당신은 여전히 모든 당신의 매핑 파일들을 배치 디스크립터 속에 명명해야 한다. 만일 당신이 옵션 HAR 배치를 사용하고자 결정하는 경우, JBoss는 당신의 HAR 파일 내에 있는 모든 매핑 파일들을 자동적으로 검출해낼 것이다.

이들 옵션들에 대한 추가 정보는 JBoss 어플리케이션 서버 사용자 가이드를 참조하라.

JMX 서비스로서 이용 가능한 또다른 특징은 런타임 Hibernate 통계이다. 3.4.6절. “Hibernate 통계”를 보라.

2.4. JCA 지원

Hibernate는 JCA 커넥터로서 구성될 수도 있다. 상세한 것은 웹 사이트를 보길 바란다. Hibernate JCA 지원은 여전히 실험적으로 검토 중에 있음을 노트하길 바란다.

2.5. 컨텍스트 상의 세션들

Hibernate를 사용하는 대부분의 어플리케이션들은 어떤 양식의 "컨텍스트상의(contextual)" 세션들을 필요로 한다. 여기서 주어진 세션은 주어진 컨텍스트의 영역에 걸쳐 활동을 한다. 하지만 어플리케이션들을 가로질러 컨텍스트를 구성하는 것에 대한 정의는 일반적으로 다르다; 그리고 다른 컨텍스트들은 현재라고 하는 개념에 대해 다른 영역들을 정의한다. 버전 3.0 전의 Hibernate를 사용하는 어플리케이션들은 자가생산된 ThreadLocal-기반의 컨텍스상의 세션들, HibernateUtil과 같은 helper 클래스들을 활용했거나 프락시/인터셉션 기반의 컨텍스트상의 세션들을 제공해주었던 (Spring 또는 Pico와 같은 )제 3의 프레임웍들을 활용하는 경향이 있었다.

버전 3.0.1에서부터 시작하여, Hibernate는 SessionFactory.getCurrentSession() 메소드를 추가했다. 초기에 이것은 JTA 트랜잭션들을 사용하는 것을 전제했다. 여기서 JTA 트랜잭션은 현재 세션의 영역과 컨텍스트를 정의했다. Hibernate 팀은 성숙된 다수의 스탠드얼론 JTA TransactionManager 구현들이 발표되면, (전부는 아니겠지만) 대부분의 어플리케이션들이 그것들이 J2EE 컨테이너 내로 배치되든 그렇지 않든 간에 JTA 트랜잭션 관리를 사용하게 될 것이라고 주장한다. 그것에 기초하여, JTA에 기반한 컨텍스트상의 세션들은 언젠가 당신이 사용을 필요로 하게 될 전부다.

하지만 버전 3.1 이후로 SessionFactory.getCurrentSession() 이면의 처리과정은 이제 플러그 가능하다. 그것을 끝내기 위해, 하나의 새로운 확장 인터페이스 (org.hibernate.context.CurrentSessionContext)와 하나의 새로운 구성 파라미터(hibernate.current_session_context_class)가 현재 세션들을 정의하는 영역과 컨텍스트의 플러그 가능성을 허용하기 위해 추가되었다.

그것의 계약에 대한 상세한 논의는 org.hibernate.context.CurrentSessionContext 인터페이스에 관한 javadocs를 보라. 그것은 하나의 메소드, currentSession()를 정의하며, 그 구현은 현재의 컨텍스트 상의 세션을 추적할 책임이 있다. 비공식적으로, Hibernate는 이 인터페이스에 대한 세 개의 구현들을 부수적으로 포함하고 있다.

  • org.hibernate.context.JTASessionContext - 현재의 세션들은 하나의 JTA에 의해 추적되고 영역화 된다. 여기서 처리과정은 이전의 JTA-전용 접근과 정확하게 동일하다. 상세한 것은 javadocs를 보라.

  • org.hibernate.context.ThreadLocalSessionContext - 현재의 세션들은 실행 쓰레드에 의해 추적된다. 상세한 것은 다시 javadocs를 보라.

처음의 두 구현들은 session-per-request로 알려지고 사용되고 있는 "하나의 세션 - 하나의 데이터베이스 트랜잭션" 프로그래밍 모형을 제공한다. 하나의 Hibernate 세션의 시작과 끝은 데이터베이스 트랜잭션의 존속 기간에 의해 정의된다. 만일 (예를 들면 순수 J2SE에서 또는 JTA/UserTransaction/BMT의 경우에) 당신이 프로그램 상의 트랜잭션 경계구분을 사용할 경우, 당신은 당신의 코드로부터 기본 트랜잭션 시스템을 은폐시키는데 Hibernate Transaction API를 사용하는 것이 권장된다. 만일 당신이 CMT를 지원하는 하나의 EJB 컨테이너에서 실행할 경우, 트랜잭션 경계들이 선언적으로 정의되고 당신은 당신의 코드 내에 어떤 트랜잭션도 세션 경계구분 오퍼레이션들을 필요로 하지 않는다. 추가 정보와 코드 예제들은 11장. 트랜잭션들과 동시성를 참조하라.

hibernate.current_session_context_class 구성 파라미터는 org.hibernate.context.CurrentSessionContext 구현이 사용될 것임을 정의한다. 역호환을 위해. 만일 이 구성 파라미터가 설정되지 않았지만 하나의 org.hibernate.transaction.TransactionManagerLookup이 구성되어 있을 경우, Hibernate는 org.hibernate.context.JTASessionContext를 사용할 것임을 노트하라. 일반적으로, 이 파라미터의 값은 단지 사용할 구현 클래스를 명명할 것이다; 하지만 두 가지 비공식적인 구현들로서 두 개의 대응하는 짧은 이름들 "jta"와 "thread"이 존재한다.