diff --git a/reference/ko/modules/architecture.xml b/reference/ko/modules/architecture.xml index 7b6b997994..291d805a54 100644 --- a/reference/ko/modules/architecture.xml +++ b/reference/ko/modules/architecture.xml @@ -236,5 +236,73 @@ + + 컨텍스트 상의 세션들 + + 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 컨테이너에서 실행할 경우, 트랜잭션 경계들이 선언적으로 정의되고 당신은 당신의 코드 내에 어떤 트랜잭션도 + 세션 경계구분 오퍼레이션들을 필요로 하지 않는다. 추가 정보와 코드 예제들은 를 참조하라. + + + + hibernate.current_session_context_class 구성 파라미터는 + org.hibernate.context.CurrentSessionContext 구현이 사용될 것임을 정의한다. 역호환을 위해. + 만일 이 구성 파라미터가 설정되지 않았지만 하나의 org.hibernate.transaction.TransactionManagerLookup이 + 구성되어 있을 경우, Hibernate는 org.hibernate.context.JTASessionContext를 사용할 것임을 + 노트하라. 일반적으로, 이 파라미터의 값은 단지 사용할 구현 클래스를 명명할 것이다; 하지만 두 가지 비공식적인 구현들로서 두 개의 + 대응하는 짧은 이름들 "jta"와 "thread"이 존재한다. + + + + diff --git a/reference/ko/modules/association_mapping.xml b/reference/ko/modules/association_mapping.xml index c8064a879d..5d4549d07b 100644 --- a/reference/ko/modules/association_mapping.xml +++ b/reference/ko/modules/association_mapping.xml @@ -292,7 +292,7 @@ create table Address ( addressId bigint not null primary key ) 양방향 연관들 - + one to many / many to one @@ -351,7 +351,14 @@ create table Address ( addressId bigint not null primary key ) ]]> - + + + 만일 기본 외래 키 컬럼이 NOT NULL일 경우 콜렉션 매핑의 <key> + 요소 상에 not-null="true"를 정의하는 것이 중요하다. 내포된 + <column> 요소 상에 not-null="true"를 + 선언하지 말고, <key> 요소 상에 선언하라. + + diff --git a/reference/ko/modules/basic_mapping.xml b/reference/ko/modules/basic_mapping.xml index bebd415a97..44993fd68f 100644 --- a/reference/ko/modules/basic_mapping.xml +++ b/reference/ko/modules/basic_mapping.xml @@ -990,7 +990,7 @@ - + version (옵션) @@ -1015,7 +1015,7 @@ type="typename" access="field|property|ClassName" unsaved-value="null|negative|undefined" - generated="true|false" + generated="never|always" insert="true|false" node="element-name|@attribute-name|element/@attribute|." />]]> @@ -1052,7 +1052,7 @@ - generated (옵션 - 디폴트는 false): + generated (옵션 - 디폴트는 never): 이 version 프로퍼티 값이 데이터베이스에 의해 실제로 산출되는지를 지정한다. 산출되는 프로퍼티들에 관한 논의를 보라. @@ -1082,7 +1082,7 @@ - + timestamp (옵션) @@ -1106,7 +1106,7 @@ access="field|property|ClassName" unsaved-value="null|undefined" source="vm|db" - generated="true|false" + generated="never|always" node="element-name|@attribute-name|element/@attribute|." />]]> @@ -1150,7 +1150,7 @@ - generated (옵션 - 디폴트는 false): + generated (옵션 - 디폴트는 never): 이 timestamp 프로퍼티 값이 데이터베이스에 의해 실제로 산출되는지를 지정한다. 산출되는 프로퍼티들에 대한 논의들 보라. @@ -1166,7 +1166,7 @@ - + 프로퍼티 @@ -1202,7 +1202,7 @@ unique="true|false" not-null="true|false" optimistic-lock="true|false" - generated="true|false" + generated="never|insert|always" node="element-name|@attribute-name|element/@attribute|." index="index_name" unique_key="unique_key_id" @@ -1278,7 +1278,7 @@ - generated (옵션 - 디폴트는 false): + generated (옵션 - 디폴트는 never): 이 프로퍼티 값이 데이터베이스에 의해 실제로 산출되는지를 지정한다. 산출되는 프로퍼티들에 대한 논의를 보라. @@ -3059,7 +3059,7 @@ public class Customer implements Serializable { - + 산출되는 프로퍼티들 산출되는 프로퍼티들은 데이터베이스에 의해 산출되는 그것들의 값들을 갖는 프로퍼티들이다. 전형적으로, @@ -3077,6 +3077,19 @@ public class Customer implements Serializable { 단순 프로퍼티들 만이 generated로 마크될 수 있다. + + never (디폴트) - 는 주어진 프로퍼티 값이 데이터베이스 내에 생성되지 않을 것임을 의미한다. + + + insert - 는 주어진 프로퍼티 값이 insert 시에 생성되지만, 차후의 업데이트들에서 다시 + 생성되지 않을 것임을 기술한다. 생성-날짜와 같은 것들이 이 카테고리 내로 포함될 것이다. 비록 + version과 + timestamp 프로퍼티들이 생성되는 것으로서 + 마크될 수 있을 지라도, 이 옵션은 거기서 이용 불가능함을 노트하라... + + + always - 는 프로퍼티 값이 insert 시와 update 시 모두에 생성됨을 기술한다. + diff --git a/reference/ko/modules/batch.xml b/reference/ko/modules/batch.xml index a27531a5b2..c214ff594e 100644 --- a/reference/ko/modules/batch.xml +++ b/reference/ko/modules/batch.xml @@ -171,7 +171,8 @@ session.close();]]> - join들은 (함축적이든 명시적이든) 대량 HQL 질의 속에 지정될 수 없다. 서브-질의들이 where-절에 사용될 수 있다; + join들은 (함축적이든 명시적이든) + 대량 HQL 질의 속에 지정될 수 없다. 서브-질의들이 where-절에 사용될 수 있다; 서브질의들 그 자신들은 조인들을 포함할 수 있다. diff --git a/reference/ko/modules/collection_mapping.xml b/reference/ko/modules/collection_mapping.xml index 3de4547d03..f3a8bc4760 100644 --- a/reference/ko/modules/collection_mapping.xml +++ b/reference/ko/modules/collection_mapping.xml @@ -144,9 +144,9 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set - lazy (옵션 - 디폴트는 true) + lazy (옵션 - 디폴트는 true)는 lazy 페칭을 사용 불가능하도록 하고 그 연관이 항상 eagerly 페치됨을 지정하는데 , 또는 대부분의 - 연산들이 콜렉션을 초기화시키지 않는 "extra-lazy" 페칭을 이용 가능하도록 하는데(매우 큰 콜렉션들에 + 연산들이 콜렉션을 초기화시키지 않는 곳에서 "extra-lazy" 페칭을 이용 가능하도록 하는데(매우 큰 콜렉션들에 적당함) 사용될 수 있다 diff --git a/reference/ko/modules/configuration.xml b/reference/ko/modules/configuration.xml index 36a0e2a1d8..3989b941a7 100644 --- a/reference/ko/modules/configuration.xml +++ b/reference/ko/modules/configuration.xml @@ -782,7 +782,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]> - +
Hibernate 트랜잭션 프로퍼티들 @@ -838,8 +838,9 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]> hibernate.transaction.flush_before_completion - 만일 사용가능토록 하면, 트랜잭션의 before completion 단계 동안에 세션이 자동적으로 flush 될 것이다. - (CMT에 대해 Hibernate를 사용할 때 매우 유용하다.) + 만일 사용가능하도록 되면, 세션은 트랜잭션의 before completion 단계 동안에 자동적으로 flush 될 것이다. + 빌드되어 있는 자동적인 세션 컨텍스트 관리가 선호되는데, + 를 보라. 예. true | false @@ -863,7 +864,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]>
- +
여러가지 프로퍼티들 @@ -875,6 +876,21 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]> + + + hibernate.current_session_context_class + + + "현재" Session의 영역화를 위한 하나의 (맞춤) 방도를 + 공급한다. 빌드되어 있는 방도들에 대한 추가 정보는 + 를 보라. + + 예. + jta | thread | + custom.Class + + + hibernate.query.factory_class @@ -1331,10 +1347,10 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]> - JTA Session 바인딩: Hibernate Session은 당신이 EJB들을 사용하고자 - 원할 경우에 JTA 트랜잭션들의 영역(scope)에 자동적으로 바인드 시킬 수도 있다. 간단하게 JNDI로부터 SessionFactory를 + JTA Session 바인딩: Hibernate Session은 + JTA 트랜잭션들의 영역(scope)에 자동적으로 바인드 시킬 수도 있다. 간단하게 JNDI로부터 SessionFactory를 룩업하고 현재 Session을 얻어라. Hibernate로 하여금 당신의 JTA 트랜잭션이 완료될 때 Session을 - flush시키고 닫는 것을 처리하도록 하라. 트랜잭션 경계 설정은 EJB 배치 디스크립터들 내에서 선언적이다. + flush시키고 닫는 것을 처리하도록 하라. 트랜잭션 경계 구분은 선언적(CMT)이거나 프로그래밍적((BMT/UserTransaction))이다. @@ -1405,7 +1421,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]> - Hibernate에 있는 몇몇 특징들(예를 들면. second level 캐시, 자동적인 JTA 및 Session 바인딩, 기타)은 관리되는 환경에서 + Hibernate에 있는 몇몇 특징들(예를 들면. second level 캐시, JTA를 가진 컨텍스트 상의 세션들, 기타.)은 관리되는 환경에서 JTA TransactionManager에 대한 접근을 필요로 한다. 어플리케이션 서버에서 당신은 Hibernate가 TransactionManager에 대한 참조를 획득하는 방법을 지정해야 한다. 왜냐하면 J2EE가 한 개의 메커니즘을 표준화 시키고 있지 않기 때문이다: @@ -1469,7 +1485,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]> - + JNDI-bound <literal>SessionFactory</literal> @@ -1501,40 +1517,48 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]> 만일 당신이 하나의 JNDI SessionFactory를 사용할 경우, 하나의 EJB 또는 어떤 다른 클래스는 JNDI - 룩업을 사용하여 SessionFactory를 얻을 수 있다. 만일 당신이 제 1장에서 소개된 하나의 Singleton - 레지스트리로서 행동하는 HibernateUtil helper 클래스를 사용할 경우 이 셋업이 필수적이지 않음을 - 노트하라. 하지만 HibernateUtil은 관리되지 않는 환경에서 보다 공통적이다. + 룩업을 사용하여 SessionFactory를 얻을 수 있다. + + 우리는 관리되는 환경들에서 SessionFactory를 JNDI에 바인드 시키고 그 밖의 경우에는 + 하나의 static 싱글톤을 사용하는 것을 권장한다. 이들 상세로부터 당신의 어플리케이션 코드를 + 은폐시키기 위해, 우리는 또한 HibernateUtil.getSessionFactory()과 같은 하나의 + helper 클래스 내에서 SessionFactory에 대한 실제 룩업 코드를 은폐시키기를 권장한다. + 그런 클래스는 또한 Hibernate를 시작하는 편리한 방법임을 노트하라— 1장을 보라. + + - - 자동적인 JTA 및 Session 바인딩 + + Current Session context management with JTA - 관리되는 환경들에서 우리는 SessionFactory를 JNDI에 바인드 시키는 것을 권장한다. 트랜잭션과 - Session 핸들링을 위해, 당신은 이미 소개된 HibernateUtil helper - 클래스를 사용할 수 있다. 하지만 EJB들은 동일한 쓰레드에서 실행되지 않을 수도 있는데, 그것은 항상 적절하게 - ThreadLocal 핸들링을 행하지 않는다(예를 들면 두 개의 세션이 서로를 호출할 때). - - - - 당신 자신의 ThreadLocal 유틸리티를 조작하는 대신, Hibernate Session을 - 얻는데 SessionFactory 상의 getCurrentSession() 메소드를 사용하라. - 만일 현재의 JTA 트랜잭션 내에 Hibernate Session이 존재하지 않을 경우, 세션이 시작되고 할당될 것이다. - hibernate.transaction.flush_before_completion과 - hibernate.transaction.auto_close_session 구성 옵션 둘 다 당신이 - getCurrentSession()으로 검색하는 모든 Session에 대해 자동적으로 설정될 - 것이고, 따라서 세션들은 또한 컨테이너가 JTA 트랜잭션들을 끝낼 때 자동적으로 flush되고 닫혀질 것이다. 이것은 - ThreadLocal 관리에 대한 대안이다. 당신이 CaveatEmptor 어플리케이션에서 - 찾을 수 있는 HibernateUtil 클래스는 실제로 두 개의 방도들 사이를 자동적으로 전환할 수 있으므로, - transaction-local, BMT, 그리고 CMT 환경들 사이에서 당신의 코드를 이식가능하게 유지할 수 있다. - - - - 예를 들어 만일 당신이 당신의 영속 계층을 작성하는데 DAO 디자인 패턴을 사용할 경우, 모든 DAO는 필요할 때 SessionFactory를 - 룩업하고 "현재(current)" Session을 연다. 제어 코드와 DAO 코드 사이에서 SessionFactory 또는 - Session의 인스턴스들을 전달할 필요가 없다. + 당신 자신의 ThreadLocal 유틸리티를 작동시키는 대신에, 우리는 또한 Hibernate Session를 + 얻기 위해 SessionFactory 상의 getCurrentSession() 메소드 사용을 + 권장한다. 현재 세션들에 관한 논의를 보라. "jta" + 세션 컨텍스트를 사용하고 있는 경우에, 현재의 JTA 트랜잭션으로 시작되고 연관된 Hibernate Session이 + 존재하지 않을 경우, 우리는 JTA 트랜잭션으로 시작되고 연관될 것이다. "jta" 컨텍스트에서 + getCurrentSession()를 통해 검색된 Session들은 그 트랜잭션이 완료되기 전에 + 자동적으로 flush될 것이고 트랜잭션 완료 후에 닫혀질 것이고, 그리고 각각의 문장 뒤에 JDBC 커넥션들을 적극적으로 해제할 것이다. + 이것은 그런 관리 사항들에 대해 사용자 코드를 명료하게 유지시켜서, 연관되어 있는 JTA 트랜잭션의 생명주기에 의해 Session들이 + 관리되도록 허용해준다. 이것은 그런 관리 사항들에 대해 사용자 코드를 명료하게 유지시켜서, 세션이 연관되어 있는 JTA 트랜잭션의 + 생명주기에 의해 관리되는 것을 Session들에게 허용해준다. 당신의 코드는 + + Session들과 트랜잭션들을 처리하는 가장 손쉬운 방법은 Hibernate의 자동적인 "현재" + Session이다. + current sessions에 관한 논의를 보라. + "jta" 세션 컨텍스트를 사용하는 경우, 현재의 JTA 트랜잭션으로 시작되고 연관된 + Hibernate Session들이 존재하지 않을 경우, 당신이 + sessionFactory.getCurrentSession()을 처음 호출할 때 하나의 세션이 현재의 JTA 트랜잭션에 대해 + 시작되고 연관될 것이다. "jta" 컨텍스트에서 getCurrentSession()을 + 통해 검색된 Session들은 그 트랜잭션이 완료되기 전에 자동적으로 flush될 것이고 + 그 트랜잭션 완료들 후에 닫혀질 것이고 각각의 문장 후에 JDBC 커넥션들을 적극적으로 해제할 것이다. + 이것은 그런 관리 사항들에 대해 사용자 코드를 명료하게 유지시켜서, 연관되어 있는 JTA 트랜잭션의 생명주기에 의해 Session들이 + 관리되도록 허용해준다. 이것은 그런 관리 사항들에 대해 사용자 코드를 명료하게 유지시켜서, 세션이 연관되어 있는 JTA 트랜잭션의 + 생명주기에 의해 관리되는 것을 Session들에게 허용해준다. 당신의 코드는 트랜잭션 경계들을 설정하는데 + UserTransaction을 통해 프로그램 상으로 JTA를 사용하거나, Hibernate Transaction API를 (이식성을 위한 코드로 권장됨) + 사용할 수 있다. 만일 당신이 하나의 EJB 컨테이너에서 실행하고 있을 경우, CMT의 경우에 선언적인 트랜잭션 경계설정이 선호된다. diff --git a/reference/ko/modules/performance.xml b/reference/ko/modules/performance.xml index 428b68ada5..af691b298a 100644 --- a/reference/ko/modules/performance.xml +++ b/reference/ko/modules/performance.xml @@ -359,7 +359,7 @@ Cat fritz = (Cat) iter.next();]]> - + 콜렉션들과 프락시들을 초기화 시키기 @@ -393,11 +393,9 @@ Cat fritz = (Cat) iter.next();]]> 웹 기반 어플리케이션에서, 서블릿 필터는 뷰 렌더링이 완료되는, 사용자 요청의 바로 끝에서만 Session을 닫는데 사용될 수 있다(Open Session in View 패턴). 물론 이것은 당신의 어플리케이션 - 인프라스트럭처의 예외상황 처리의 정정에 관한 무거운 요구를 부과한다. 사용자에게 반환하기 전에, 심지어 예외상황이 - 뷰의 렌더링 동안 발생할 때, Session이 닫혀지고 트랜잭션이 종료되는 것은 지극히 중요하다. - 서블릿 필터는 이 접근법으로 Session에 접근하는 것이 가능해야 한다. 우리는 - ThreadLocal 변수가 현재의 Session을 보관하는데 사용되는 것을 - 권장한다(예제 구현에 대해서는 1장, 를 보라). + 인프라스트럭처의 예외상황 처리의 정정에 관한 무거운 요구를 부과한다. + 뷰 렌더링 동안에 하나의 예외상황이 발생할때에도 사용자에게 반환되기 전에 Session이 닫혀지고 + 트랜잭션이 종료되는 것은 지극히 중요하다. 이 "Open Session in View" 패턴에 관한 예제들은 Hibernate 위키를 보라. diff --git a/reference/ko/modules/query_criteria.xml b/reference/ko/modules/query_criteria.xml index 7a11615d62..63ca6b6b59 100644 --- a/reference/ko/modules/query_criteria.xml +++ b/reference/ko/modules/query_criteria.xml @@ -61,7 +61,7 @@ List cats = crit.list();]]> @@ -119,9 +119,9 @@ List cats = sess.createCriteria(Cat.class) diff --git a/reference/ko/modules/query_hql.xml b/reference/ko/modules/query_hql.xml index 6e54c1b54d..f64d387072 100644 --- a/reference/ko/modules/query_hql.xml +++ b/reference/ko/modules/query_hql.xml @@ -67,7 +67,7 @@ - + 연관들과 조인들 @@ -149,9 +149,11 @@ left join fetch child.kittens]]> - fetch 구조체는 scroll() - 또는 iterate()를 사용하여 호출된 질의들 내에 사용될 수 없음을 노트하라. fetch는 - setMaxResults() 또는 setFirstResult()와 함께 사용될 수도 없을 것이다. + (비록 scroll()이 사용될 수 있을지라도) fetch 구조체는 + iterate()를 사용하여 호출되는 질의들 내에 사용될 수 없음을 노트하라. 이들 오퍼레이션들이 결과 행들에 + 기초하고 있기 때문에 fetchsetMaxResults() 또는 + setFirstResult()과 함께 사용되지 말아야 하며, 그것들(결과 행들)은 대개 각각의 eager 콜렉션 페칭에 대해 + 중복들을 포함하므로 많은 행들이 당신이 기대하는 것이 아니다. fetch는 특별한 용도의 with 조건과도 함께 사용될 수 없다.한 개의 질의 내에 하나 이상의 콜렉션을 조인 페칭시켜 카티젼 곱을 생성시키는 것이 가능한데, 이 경우에 주의하라. 다중 콜렉션 role들을 조인 페칭시키는 것은 또한 때때로 bag 매핑들에 대해 예기치 않은 결과들을 가져다주기 때문에, 당신이 이 경우에 당신의 질의들을 처방하는 방법에 대해 주의하라. @@ -167,6 +169,27 @@ + + + join 구문의 형식들 + + + HQL은 두 가지 형식의 연관 조인을 지원한다: 암묵적 그리고 명시적. + + + + 앞의 절에서 보여진 질의들은 모두 join 키워드가 from 절 내에 명시적으로 사용되는 명시적인 형식을 + 사용한다. 이것은 권장되는 형식이다. + + + + 함축적인 형식은 join 키워드를 사용하지 않는다. 대신에, 연관들은 dot(.) 표기를 + 사용하여 "dot-참조된다(dereferenced)". 함축적인 조인들은 임의의 HQL 절들내에 + 나타날 수 있다. 함축적인 join은 결과되는 SQL 문장에서 inner join으로 귀결된다. + + + + select 절 diff --git a/reference/ko/modules/query_sql.xml b/reference/ko/modules/query_sql.xml index 320eed1bf2..6f458d2e78 100644 --- a/reference/ko/modules/query_sql.xml +++ b/reference/ko/modules/query_sql.xml @@ -342,14 +342,15 @@ List loggedCats = sess.createSQLQuery(sql) - + 질의를 위한 내장 프로시저 사용하기 - Hibernate 3은 내장 프로시저들을 통한 질의들에 대한 지원을 도입한다. 내장 프로시저들은 Hibernate와 동작하는 것이 - 가능하도록 첫 번째 출력-파라미터로서 한 개의 결과셋을 반환해야 한다. Oracle9 이상의 버전에서 그런 내장 프로시저에 - 대한 예제는 다음과 같다: + Hibernate 3은 내장 프로시저들과 함수들을 통한 질의 지원을 도입한다. 대부분의 다음 문서는 양자 모두에 동일하게 적용된다. + 내장 프로시저/함수는 Hibernate와 동작하는 것이 가능하도록 첫 번째 out-파라미터로서 한 개의 결과셋을 반환해야 한다. + Oracle9 이상의 버전에서 그런 내장 프로시저에 대한 예제는 다음과 같다: + <load-collection>은 지원되지 않는다. - + 내장 프로시저들을 사용하는 규칙들/제약들 - Hibernate에서 내장 프로시저들을 사용하기 위해서 프로시저들은 다음 몇몇 규칙들을 따라야 한다. 만일 그것들이 그들 규칙들을 + Hibernate에서 내장 프로시저들을 사용하기 위해서 프로시저들/함수들은 다음 몇몇 규칙들을 따라야 한다. 만일 그것들이 그들 규칙들을 따르지 않을 경우 그것들은 Hibernate와 함께 사용 불가능하다. 만일 당신이 여전히 이들 프로시저들을 사용하고자 원할 경우, 당신은 session.connection()을 통해 그것들을 실행시켜야 한다. 데이터베이스 벤더들이 다른 내장 프로시저 의미론/구문을 갖고 있기 때문에, 규칙들은 각각의 데이터베이스에 따라 차이가 난다. @@ -402,23 +403,21 @@ BEGIN 내장 프로시저 질의들은 setFirstResult()/setMaxResults()로서 쪽매김 될 수 없다. - + 권장되는 호출 형식은 표준 SQL92이다: { ? = call + functionName(<parameters>) } 또는 { ? = call + procedureName(<parameters>}. Native 호출 구문은 지원되지 않는다. + + Oracle의 경우 다음 규칙들이 적용된다: - - - 프로시저는 한 개의 결과 셋을 반환해야 한다. 이것은 Oracle 9 또는 10에서 한 개의 SYS_REFCURSOR를 - 반환함으로써 행해진다. Oracle에서 당신은 한 개의 REF CURSOR 타입을 정의할 필요가 있다. - - - - - 권장되는 형식은 { ? = call procName(<parameters>) } 또는 - { ? = call procName }이다.(이것은 Hibernate 규칙이라기 보다는 Oracle 규칙이다.) - - + + 하나의 함수는 하나의 결과 셋을 반환해야 한다. 프로시저의 첫 번째 파라미터는 하나의 결과 셋을 반환하는 + 하나의 OUT이어야 한다. 이것은 Oracle 9 또는 10에서 하나의 SYS_REFCURSOR를 + 사용하여 행해진다. Oracle에서 당신이 REF CURSOR 타입을 정의할 필요가 있다면, Oracle 보고서를 보라. + + diff --git a/reference/ko/modules/session_api.xml b/reference/ko/modules/session_api.xml index 8ced12ec35..0670fb83b2 100644 --- a/reference/ko/modules/session_api.xml +++ b/reference/ko/modules/session_api.xml @@ -195,7 +195,7 @@ sess.refresh(cat); //re-read the state (after the trigger executes)]]> - + 질의들을 실행하기 @@ -222,12 +222,18 @@ List kittens = session.createQuery( Cat mother = (Cat) session.createQuery( "select cat.mother from Cat as cat where cat = ?") .setEntity(0, izi) - .uniqueResult();]]> + .uniqueResult();]] + +Query mothersWithKittens = (Cat) session.createQuery( + "select mother from Cat as mother left join fetch mother.kittens"); +Set uniqueMothers = new HashSet(mothersWithKittens.list());]]> 하나의 질의는 대개 list()를 호출하여 실행되고, 질의의 결과는 메모리 내에서 하나의 콜렉션 속으로 전체적으로 로드될 것이다. 하나의 질의에 의해 검색된 엔티티 인스턴스들은 영속(persistent) 상태에 있다. 당신의 질의가 - 하나의 객체를 오직 반환할 것임을 당신이 알고 있을 경우에 uniqueResult() 메소드는 단축을 제공한다. + 하나의 객체를 오직 반환할 것임을 당신이 알고 있을 경우에 uniqueResult() 메소드는 단축을 제공한다. + 콜렉션들에 대해 eager 페칭을 사용하는 질의들은 대개 (그것들의 초기화된 콜렉션들을 가진) 루트 객체들에 대한 중복들을 대개 + 반환한다. 당신은 Set을 통해 이들 중복들을 간단하게 필터링할 수 있다. @@ -951,7 +957,7 @@ sess.close();]]> - + Transitive persistence(전이 영속) @@ -1080,6 +1086,13 @@ sess.close();]]> + + 마지막으로 오퍼레이션들의 케스케이딩이 호출 시점에서 또는 flush 시점에서 + 객체 그래프에 적용될 수 있음을 노트하라. 이용 가능할 경우에 모든 오퍼레이션들은 그 오퍼레이션이 실행될 때 도달 가능한 연관된 + 엔티티들에 대해 케스케이드 된다. 하지만 save-upatedelete-orphan은 + Session의 flush 동안에 도달 가능한 모든 연관된 엔티티들에 대해 이행적(transitive)이다. + + 메타데이터 사용하기 diff --git a/reference/ko/modules/transactions.xml b/reference/ko/modules/transactions.xml index 9175adb7a7..f012df7733 100644 --- a/reference/ko/modules/transactions.xml +++ b/reference/ko/modules/transactions.xml @@ -1,25 +1,30 @@ - + 트랜잭션들과 동시성 Hibernate와 동시성 제어에 대한 가장 중요한 점은 이해하기가 매우 쉽다는 점이다. Hibernate는 어떤 추가적인 잠금 행위 없이 JDBC 커넥션들과 JTA 리소스들을 직접 사용한다. 우리는 당신의 데이터베이스 관리 시스템의 JDBC, ANSI, 그리고 트랜잭션 격리 명세에 - 약간의 시간을 할애할 것을 매우 권장한다. Hibernate는 단지 자동적인 버전화를 추가하지만 메모리 내에서 객체들을 잠그지 않거나 당신의 - 데이터베이스 트랜잭션들의 격리 레벨을 변경시키지 않는다. 기본적으로, 당신이 당신의 데이터베이스 리소스들에 직접 JDBC(또는 JTA/CMT)를 - 사용하는 것처럼 Hibernate를 사용하라. + 약간의 시간을 할애할 것을 매우 권장한다. - 하지만, 자동적인 버전화에 덧붙여, Hibernate는 또한 SELECT FOR UPDATE 구문을 사용하여, - 행들에 대한 pessimistic 잠금을 위한 (마이너) API를 제공한다. 이 API는 이 장의 뒷 부분에서 논의된다. + Hibernate는 메모리 내에서 객체들을 잠그지 않는다. 당신의 어플리케이션은 격리 레벨에 의해 정의된 대로 행위를 기대할 수 있다. + 또한 transaction-영역의 캐시인 Session 덕분에, Hibernate는 (스칼라 값들을 반환하는 질의들을 보고하지 않는) + 식별자와 엔티티 질의들에 의한 룩업을 위해 반복 가능한 읽기를 제공한다. + + + + 자동적인 optimistic 동시성 제어를 위한 버전화에 덧붙여, Hibernate는 또한 SELECT FOR UPDATE + 구문을 사용하여 행들에 대한 pessimistic 잠금을 위한 하나의 (마이너)API를 제공한다. optimistic 동시성 제어와 이 API는 + 이 장의 뒷부분에서 논의된다. 우리는 Configuration, SessionFactory, Session, - 알갱이를 가진 Hibernate에서의 동시성 제어 뿐만 아니라 데이터베이스 트랜잭션과 긴 어플리케이션 트랜잭션에 대한 논의를 시작한다. + 알갱이를 가진 Hibernate에서의 동시성 제어 뿐만 아니라 데이터베이스 트랜잭션과 장기간에 걸친 (컴퓨터와의)대화들에 대한 논의를 시작한다. - + 세션 영역과 트랜잭션 영역 @@ -29,17 +34,17 @@ - Session은 단일 비지니스 프로세스, 하나의 작업 단위를 위해 한번만 사용되고 나서 폐기될 예정인, - 비용이 들지 않는, 쓰레드 안전하지 않은 객체이다. Session은 그것이 필요하지 않으면 JDBC - Connection(또는 Datasource)를 얻지 않을 것이어서, 데이터 접근이 - 특별한 요청에 서비스할 필요가 있을 것이라고 당신이 확신하지 않을 경우에 당신은 Session을 안전하게 - 열고 닫을 수 있다. (이것은 당신이 요청 인터셉션을 사용하여 다음 패턴들 중 어떤 것을 구현하자마자 중요하게 된다.) + Session은 하나의 요청, 하나의 대화 , 하나의 작업 단위를 위해 한번만 사용되고 나서 폐기될 예정인, + 비용이 들지 않는, 쓰레드 안전하지 않은 객체이다. Session은 커넥션이 필요하지 않으면 하나의 JDBC + Connection(또는 Datasource)를 얻지 않을 것이므로, 사용될 때까지 + 리소스들을 소비하지 않는다. 이 그림을 완성하기 위해 당신은 또한 데이터베이스 트랜재션들에 대해 생각해야 한다. 데이터베이스 트랜잭션은 데이터베이스에서 잠금 다툼을 줄이기 위해 가능한 짧아야 한다. 긴 데이터베이스 트랜잭션들은 당신의 어플리케이션이 고도의 동시성 로드로의 가용성을 - 높이는 것을 방해할 것이다. + 높이는 것을 방해할 것이다. 그러므로 사용자가 생각하는 시간 동안 단위 작업이 완료될 때까지 데이터베이스 트랜잭션을 열려진채로 + 소유하는 것은 대개 결코 좋은 설계는 아니다. @@ -58,7 +63,10 @@ 작업 단위 속으로 그룹지워진다. (이것은 또한 모든 하나의 SQL 문장 뒤의 auto-commit(자동-커밋)이 어플리케이션 내에서 무용지물임을 의미하고, 이 모드가 SQL 콘솔 작업을 돕도록 고안되었음을 노트하라. Hibernate는 의미하고, 이 모드는 Hibernate는 즉시 자동-커밋 모드를 사용 불가능하게 하거나, 어플리케이션 서버가 그렇게 행하고, - 즉시 자동-커밋시키는 것을 사용불가능하게 하거나 ,그렇게 행하는 것을 기대한다.) + 즉시 자동-커밋시키는 것을 사용불가능하게 하거나 ,그렇게 행하는 것을 기대한다.) 데이터베이스 트랜잭션들은 결코 옵션이 아니며, + 하나의 데이터베이스와의 모든 통신은 당신이 데이터를 읽든 쓰단간에 상관없이 하나의 트랜잭션 내에서 발생해야 한다. + 설명하였듯이, 데이터 읽기를 위한 auto-commit 특징을 피해야 할 것이며, 많은 작은 트랜잭션들은 하나의 명료하게 정의된 + 작업 단위보다 더 좋게 수행될 것 같지 않다. 후자가 또한 훨씬 더 유지가능하고 확장적이다. @@ -69,23 +77,37 @@ Session을 열고 닫을 때 그것을 시작하고 커밋시켜서 클라이언트 요청에 서비스하는데 한 개의 데이터베이스 트랜잭션을 사용하게 될 것이다. 둘 사이의 관계는 일대일 대응이고 이 모형은 많은 어플리케이션들에서 완전하게 적합하다. + + + 난제는 구현에 놓여있다: Hibernate는 이 패턴을 단순화 시키기 위해 "현재 세션"에 관한 미리 빌드된 관리를 제공한다. 당신이 + 행해야할 모든 것은 서버 요청이 처리되어야 할 때 트랜잭션을 시작하고, 그 응답이 클라이언트로 전송되기 전에 트랜잭션을 끝내는 + 것이다. 당신은 당신이 좋아하는 임의의 방법으로 이것을 행할 수 있으며, 공통된 해결책들은 서비스 메소드들 상의 첨단, 또는 + 하나의 프락시/인터셉션 컨테이너를 가진 APO 인터셉터인, ServletFilter이다. 하나의 EJB + 컨테이너는 CMT의 경우에 선언적으로 EJB session beans 상에 트랜잭션 경계구분과 같은 동시 대조 측면들을 구현하는 + 표준 방법이다. 만일 당신이 프로그램 상의 트랜잭션 경계구분을 사용하고자 결정한다면, 사용의 용이성과 코드 이식성을 위해 + 이 장의 뒷 부분에서 보여진 Hibernate Transaction을 선호하라. + - 난제는 구현에 놓여있다: Session과 트랜잭션이 정확하게 시작되고 끝나야 할 뿐만 아니라, 그것들은 - 또한 데이터 접근 오퍼레이션들에 대해 접근 가능해야 한다. 작업의 단위에 대한 경계 구분은 하나의 요청이 서버에 도착하고 - 응답이 전송되기 전에 실행되는 인터셉터(예를 들면 ServletFilter)를 사용하여 이상적으로 구현된다. - 우리는 하나의 ThreadLocal 변수를 사용하여 그 Session을 요청에 서비스하는 - 쓰레드에 바인드 시킬 것을 권장한다. 이것은 이 쓰레드 내에서 실행되는 모든 코드에서 (static 변수에 접근하는 것처럼) 쉽게 - 접근을 허용해준다. 당신이 선택하는 데이터베이스 트랜잭션 경계 구분 메커니즘에 따라, 당신은 또한 ThreadLocal - 변수 내에 트랜잭션 컨텍스트를 유지할 수도 있다. 이를 위한 구현 패턴들은 ThreadLocal Session 및 - Open Session in View으로 알려져 있고 Hibernate Wiki 상에서 찾을 수 있다. 물론 당신은 - 하나의 인터셉터를 구현하고 그것을 당신의 환경에 설정하는 방법을 찾아야 한다. 팁들과 예제들은 Hibernate 웹 사이트를 보라. + 당신의 어플리케이션 코드는 어디서든 필요할 때 종종 sessionFactory.getCurrentSession()을 + 간단히 호출함으로써 요청을 처리할 "현재 세션"에 접근할 수 있다. 당신은 현재 데이터베이스 트랜잭션으로 영역화된 하나의 + Session을 항상 얻게 될 것이다. 이것은 resource-local 환경 또는 JTA 환경에 대해 구성되어야 + 하며, 을 보라. + + + + 때때로 "뷰가 렌더링될 때까지" 하나의 Session 과 데이터베이스 트랜잭션의 영역을 확장시키는 것이 + 편리하다. 이것은 요청이 처리된 후에 하나의 별도의 렌더링 단계를 활용하는 서블릿 어플리케이션들에서 특히 유용하다. + 뷰 렌더링이 완료될 때까지 데이터베이스 트랜잭션을 확장하는 것은 당신이 당신 자신의 인터셉터를 구현하는 경우에 행하기가 쉽다. + 하지만 만일 당신이 컨테이너에 의해 관리되는 트랜잭션들을 가진 EJB들에 의존할 경우에, 하나의 EJB 메소드가 반환될 때 + 임의의 뷰 렌더링이 시작될 수 있기 전에 하나의 트랜잭션이 완료되기 때문에, 행하는 것이 쉽지 않다. 이 + Open Session in View 패턴을 둘러싼 팁들과 예제들은 Hibernate 웹 사이트와 포럼을 보라. - - 어플리케이션 트랜잭션들 + + 장기간의 대화 session-per-request 패턴은 당신이 작업 단위들을 설계하는데 사용할 수 있는 유일한 유용한 개념이 아니다. 많은 비지니스 @@ -110,7 +132,8 @@ - 우리는 사용자의 관점에서, 이것을 작업 단위, 장기간 실행되는 어플리케이션 트랜잭션이라고 명명한다. + 우리는 사용자의 관점에서, 이것을 작업 단위, 장기간 실행되는 대화 + (또는 어플리케이션 트랜잭션)이라고 명명한다. 당신이 당신의 어플리케이션에서 이것을 어떻게 구현할 수 있는 많은 방법들이 존재한다. @@ -122,19 +145,20 @@ - 명료하게, 우리는 어플리케이션 트랜잭션을 구현하는데 몇몇 데이터베이스 트랜잭션들을 사용해야 한다. 이 경우에, - 비지니스 프로세스들의 격리를 유지하는 것은 어플리케이션 티어의 부분적인 책임이 된다. 단일 어플리케이션 트랜잭션은 - 대개 여러 개의 데이터베이스 트랜잭션들에 걸친다. 그것은 이들 데이터베이스 트랜잭션들 중 오직 한 개(마지막 트랜잭션)가 - 업데이트된 데이터를 저장하고, 모든 다른 트랜잭션들이 단순히 데이터를 읽는 (예를 들면, 몇몇 요청/응답 주기에 걸치는 - 마법사 스타일의 대화 상자에서) 경우에만 원자단위가 될 것이다. 특히 당신이 Hibernate의 특징들을 사용할 경우에 , 이것은 - 들리는 것보다 구현하기가 더 쉽다: + 명료하게, 우리는 대화(어플리케이션 트랜잭션)를 구현하는데 몇몇 데이터베이스 트랜잭션들을 + 사용해야 한다. 이 경우에, 비지니스 프로세스들의 격리를 유지하는 것은 어플리케이션 티어의 부분적인 책임이 된다. + 단일 대화는 대개 여러 개의 데이터베이스 트랜잭션들에 걸친다. 그것은 이들 데이터베이스 트랜잭션들 중 + 오직 한 개(마지막 트랜잭션)가 업데이트된 데이터를 저장하고, 모든 다른 트랜잭션들이 단순히 데이터를 읽는 (예를 들면, + 몇몇 요청/응답 주기에 걸치는 마법사 스타일의 대화 상자에서) 경우에만 원자단위가 될 것이다. 특히 당신이 Hibernate의 + 특징들을 사용할 경우에 , 이것은 들리는 것보다 구현하기가 더 쉽다: 자동적인 버전화 - Hibernate는 당신을 위해 자동적인 optimistic - 동시성 제어를 행할 수 있고, 그것은 사용자가 생각하는 시간 동안 동시적인 변경이 발생했는지를 자동적으로 검출할 수 있다.. + 동시성 제어를 행할 수 있고, 그것은 사용자가 생각하는 시간 동안 동시적인 변경이 발생했는지를 자동적으로 검출할 수 있다. + 대개 우리는 오직 대화의 끝에서 체크한다. @@ -148,17 +172,18 @@ - Long Session - Hibernate Session은 데이터베이스 + 확장된 (또는 Long) Session - Hibernate Session은 데이터베이스 트랜잭션이 커밋된 후에 기본 JDBC 커넥션이 연결 해제될 수도 있고, 새로운 클라이언트 요청이 발생할 때 다시 연결될 수 - 있다. 이 패턴은 session-per-application-transaction(어플리케이션 트랜잭션 당 세션)으로 - 알려져 있고 재첨부를 불필요하게 만든다. 자동적인 버전화는 동시성 변경들을 격리시키는데 사용된다. + 있다. 이 패턴은 session-per-conversation(대화 당 세션)으로 + 알려져 있고 재첨부를 불필요하게 만든다. 자동적인 버전화는 동시성 변경들을 격리시키는데 사용되고 Session은 + 자동적으로 flush되는 것이 허용되지 않지만 명시적으로 flush되는 것은 허용된다. session-per-request-with-detached-objects과 - session-per-application-transaction 양자는 장점들과 단점들을 갖는데, 우리는 이 장의 + session-per-conversation 양자는 장점들과 단점들을 갖는데, 우리는 이 장의 뒷 부분에서 optimistic 동시성 제어 단락에서 그것들을 논의한다. @@ -279,7 +304,8 @@ 데이터베이스 (또는 시스템) 트랜잭션 경계들은 항상 필수적이다. 데이터베이스와의 통신은 데이터베이스 트랜잭션의 외부에서 발생할 수 없다(이것은 자동-커밋 모드로 사용되는 많은 개발자들에게는 혼동스러워 보인다). 항상 심지어 읽기 전용 오퍼레이션들에 대해서도 명료한 트랜잭션 경계들을 사용하라. 당신의 격리 레벨과 데이터베이스 가용성들에 따라, 이것은 필요하지 않을 수 있지만, 만일 당신이 항상 - 트랜잭션들을 명시적으로 경계 설정할 경우에는 하강하는 결점들이 존재하지 않는다. + 트랜잭션들을 명시적으로 경계 설정할 경우에는 하강하는 결점들이 존재하지 않는다. 확실히, 하나의 데이터베이스 트랜잭션은 심지어 + 데이터 읽기조차도 많은 작은 트랜잭션들의 경우보다는 더 좋게 수행될 것이다. @@ -287,14 +313,19 @@ 관리되는 J2EE 환경에서 실행될 수 있다. 관리되지 않는 환경에서, Hibernate는 대개 그것 자신의 데이터베이스 커넥션 풀에 대한 책임이 있다. 어플리케이션 개발자는 트랜잭션 경계들을 손수 설정해야 한다. 달리 말해, 개발자 스스로 데이터베이스 트랜잭션들을 시작하고, 커밋시키거나 롤백시켜야 한다. 관리되는 환경은 대개 예를 들어 EJB 세션 빈즈의 배치 디스크립터 속에 선언적으로 정의된 - 트랜잭션 어셈블리를 가진, 컨테이너에 의해-관리되는 트랜잭션들을 제공한다. 그때 프로그램 상의 트랜잭션 경계 설정은 더 이상 필요하지 - 않다. 심지어 Session을 flush 시키는 것이 자동적으로 행해진다. + 트랜잭션 어셈블리를 가진, 컨테이너에 의해-관리되는 트랜잭션들(CMT)을 제공한다. 그때 프로그램 상의 트랜잭션 경계 설정은 더 이상 필요하지 + 않다. - 하지만, 당신의 영속 계층이 이식성을 유지하게끔 자주 희망된다. Hibernate는 당신의 배치 환경의 고유한 트랜잭션 시스템 속으로 - 변환되는 Transaction이라 명명되는 wrapper API 를 제공한다. 이 API는 실제로 옵션이지만 우리는 - 당신이 CMT session bean 속에 있지 않는 한 그것의 사용을 강력하게 권장한다. + However, it is often desirable to keep your persistence layer portable between non-managed + resource-local environments, and systems that can rely on JTA but use BMT instead of CMT. + In both cases you'd use programmatic transaction demaracation. + 하지만, CMT 대신 BMT를 사용하는 JTA에 의존할 수 있는 시스템들, 그리고 관리되지 않는 resource-local 환경들 사이에서 + 당신의 영속 계층에 이식성을 유지시키는 것이 자주 희망된다. 두 경우들에서 당신은 프로그램 상의 트랜잭션 경계설정을 사용할 것이다. + Hibernate는 당신의 배치 환경의 고유한 트랜잭션 시스템 속으로 변환되는 Transaction이라 명명되는 + wrapper API 를 제공한다. 이 API는 실제로 옵션이지만 우리는 당신이 CMT session bean 속에 있지 않는 한 그것의 사용을 + 강력하게 권장한다. @@ -330,12 +361,13 @@ - + 관리되지 않는 환경 - 만일 Hibernate 영속 계층이 관리되지 않는(non-managed) 환경에서 실행될 경우, 데이터베이스 커넥션들은 대개 Hibernate의 - 풀링 메커니즘에 의해 처리된다. session/transaction 처리 관용구는 다음과 같다: + 만일 Hibernate 영속 계층이 관리되지 않는(non-managed) 환경에서 실행될 경우, 데이터베이스 커넥션들은 대개 Hibernate가 + 필요로할 때 커넥션들을 획득하는 간단한 (예를 들면 DataSource가 아닌) 커넥션 풀(pool)들로부터 처리된다. + session/transaction 처리 관용구는 다음과 같다: - 또는 다음과 같을 수 있다: + 당신은 Session을 명시적으로 flush() 하지 말아야 한다 - + commit()에 대한 호출은 (그 세션에 대한 + FlushMode에 따라)자동적으로 동기화를 트리거시킨다. + close()에 대한 호출은 세션의 끝을 마크한다. close()의 + 주된 구현은 JDBC 커넥션이 그 세션에 의해 포기될 것이라는 점이다. 이 Java 코드는 관리되지 않는 환경과 + JTA 환경 양자에서 이식성이 있고 실행된다. - + 보다 더 유연한 해결책은 앞서 설명했듯이 Hibernate의 미리 빌드되어 있는 "현재 세션" 컨텍스트 관리이다: + + + - - 당신은 Session을 명시적으로 flush()시키지 말아야 한다 - - commit() 호출은 동기화를 자동적으로 트리거 시킨다. - - - - close() 호출은 세션의 종료를 마크한다. close()의 주된 의미는 - JDBC 커넥션이 그 세션에 의해 포기될 것이라는 점이다. - - - - 이 자바 코드는 이식성이 있고 관리되지 않는 환경과 JTA 환경 양자에서 실행된다. - - 당신은 통상의 어플리케이션에서 비지니스 코드 속에 이 관용구를 결코 보지 않을 것이다; 치명적인(시스템) 예외상황들은 항상 - "상단"에서 잡혀야 한다. 달리 말해, Hibernate를 실행하는 코드가 (영속 계층에서) 호출되고 RuntimeException을 - 처리하는 (그리고 대개 오직 제거하고 빠져나갈 수 있는) 코드는 다른 계층들 속에 있다. 이것은 당신 자신이 설계하는 난제일 - 수 있고 당신은 J2EE/EJB 컨테이너 서비스들이 이용 가능할 때마다 J2EE/EJB 컨테이너 서비스들을 사용할 것이다. 예외상황 + "상단"에서 잡혀야 한다. 달리 말해, (영속 계층에서) Hibernate 호출들을 실행시키는 코드와 RuntimeException을 + 처리하(고 대개 오직 제거하고 빠져나갈 수 있는) 코드는 다른 계층들 속에 있다. Hibernate에 의한 현재 컨텍스트 관리는 이 설계를 + 현격하게 단순화시켜서, 당신이 필요로 하는 모든 것은 SessionFactory에 대한 접근이다.예외상황 처리는 이 장의 뒷부분에서 논의된다. - 당신은 (디폴트인) org.hibernate.transaction.JDBCTransactionFactory를 선택해야 함을 노트하라. + 당신은 (디폴트인) org.hibernate.transaction.JDBCTransactionFactory를 선택해야 하고, + 두번째 예제의 경우 당신의 hibernate.current_session_context_class를 선택해야 함을 노트하라. - + JTA 사용하기 만일 당신의 영속 계층이 어플리케이션 서버에서(예를 들어, EJB 세션 빈즈 이면에서) 실행될 경우, Hibernate에 의해 - 획득된 모든 데이터소스 커넥션은 자동적으로 전역 JTA 트랜잭션의 부분일 것이다. Hibernate는 이 통합을 위한 두 개의 - 방도들을 제공한다. + 획득된 모든 데이터소스 커넥션은 자동적으로 전역 JTA 트랜잭션의 부분일 것이다. 당신은 또한 스탠드얼론 JTA 구현을 + 설치할 수 있고 EJB 없이 그것을 사용할 수 있다. Hibernate는 JTA 통합을 위한 두 개의 방도들을 제공한다. @@ -444,82 +466,66 @@ finally { }]]> - 또는: + 만일 당신이 트랜잭션에 묶인 Session, 즉 쉬운 컨텍스트 보급을 위한 + getCurrentSession() 기능을 사용하고자 원할 경우, 당신은 + JTA UserTransaction API를 직접 사용해야 할 것이다: - - CMT의 경우, 트랜잭션 관할[경계 설정]은 프로그램 상이 아닌, session bean 배치 디스크립터들 속에서 행해진다. 당신이 스스로 - Session을 수작업으로 flush 시키고 닫고자 원하지 않을 경우, 단지 - hibernate.transaction.flush_before_completiontrue로 설정하고, - hibernate.connection.release_modeafter_statement 또는 - auto로 설정하고 hibernate.transaction.auto_close_session을 - true로 설정하라. Hibernate는 그때 자동적으로 flush 되고 당신을 위해 Session을 - 닫을 것이다. 남아 있는 유일한 작업은 예외상황이 발생할 때 트랜잭션을 롤백시키는 것이다. 다행하게도 CMT bean에서, 이것이 자동적으로 - 일어난다. 왜냐하면 session bean 메소드에 의해 던져진 처리되지 않은 RuntimeException은 전역 트랜잭션을 - 롤백시키도록 컨테이너에게 통보하기 때문이다. 이것은 당신이 CMT에서 Hibernate Transaction API를 - 사용할 필요가 전혀 없음을 의미한다. + CMT의 경우, 트랜잭션 관할[경계 설정]은 프로그램 상이 아닌, session bean 배치 디스크립터들 속에서 행해진다. + 그러므로 코드는 다음으로 감소된다: - - 당신이 Hibernate의 트랜잭션 팩토리를 구성할 때, 당신이 BMT session bean에서 - org.hibernate.transaction.JTATransactionFactory를 선택해야하고, CMT session bean에서 - org.hibernate.transaction.CMTTransactionFactory를 선택해야 함을 노트하라. 또한 - org.hibernate.transaction.manager_lookup_class를 설정하는 것을 염두에 두라. - - - - 만일 당신이 CMT 환경에서 작업하고 있고, 세션을 자동적으로 flushing하고 닫는 것을 사용할 경우, 당신은 또한 당신의 코드의 다른 - 부분들에서 동일한 세션을 사용하고자 원할 수도 있다. 일반적으로 관리되지 않는 환경에서 당신은 세션을 소유하는데 하나의 - ThreadLocal 변수를 사용할 것이지만, 한 개의 EJB 요청은 다른 쓰레드들(예를 들면 또 다른 세션 빈을 - 호출하는 세션 빈) 내에서 실행될 수도 있다. 만일 당신이 당신의 Session 인스턴스를 전달하는 것을 - 고민하고 싶지 않다면, SessionFactory이 JTA 트랜잭션 컨텍스트에 바인드되어 있는 한 개의 세션을 - 반환하는, getCurrentSession() 메소드를 제공한다. 이것은 Hibernate를 어플리케이션 속으로 - 통합시키는 가장 손쉬운 방법이다! "현재" 세션은 (위의 프로퍼티 설정들에 관계없이) auto-flush와 auto-close, 그리고 - auto-connection-release를 항상 이용 가능하게 한다. 우리의 session/transaction 관리 idiom은 다음과 같이 감소된다: - - - - 달리 말해, 당신이 관리 환경에서 행해야 하는 모든 것은 SessionFactory.getCurrentSession()을 - 호출하고, 당신의 데이터 접근 작업을 행하고, 그리고 나머지를 컨테이너에게 남겨두는 것이다. 트랜잭션 경계들은 당신의 - session bean의 배치 디스크립터들 속에 선언적으로 설정된다. 그 세션의 생명주기는 Hibernate에 의해 완전하게 관리된다. + 왜냐하면 하나의 세션 빈 메소드에 의해 던져진 처리되지 않은 RuntimeException이 + 글로벌 트랜잭션을 rollback으로 설정하도록 컨테이너에게 알려주기 때문에, CMT/EJB에서조차 롤백은 자동적으로 발생된다. + 이것은 당신이 BMT 이든 CMT이든 모두에서 Hibernate Transaction API를 사용할 필요가 + 없으며, 당신은 그 트랜잭션에 묶인 "현재" Session의 자동적인 보급(propagation)을 얻게 됨을 의미한다. - + - after_statement 커넥션의 사용에는 한 가지 단서가 존재한다. JTA 명세서의 분별없는 제약성으로 인해, - scroll() 또는 iterate()에 의해 반환된 어떤 닫혀지지 않은 - ScrollableResults 또는 Iterator 인스턴스들을 Hibernate가 자동적으로 - 제거하는 것이 불가능하다. 당신은 finally 블록에서 ScrollableResults.close() - 또는 Hibernate.close(Iterator)를 명시적으로 호출하여 기본 데이터베이스 커서를 - 해제시켜야 한다. (물론 대부분의 어플리케이션들은 CMT 코드에서 scroll() - 또는 iterate() 사용을 쉽게 피할 수 있다.) + 당신이 Hibernate의 트랜잭션 팩토리를 구성할 때, 당신이 JTA를 직접 사용할 경우(BMT) 당신은 + org.hibernate.transaction.JTATransactionFactory를 선택해야하고, CMT session bean에서는 + org.hibernate.transaction.CMTTransactionFactory를 선택해야 함을 노트하라. 또한 + org.hibernate.transaction.manager_lookup_class를 설정하는 것을 염두에 두라. 게다가 + 반드시 당신의 hibernate.current_session_context_class이 설정되지 않도록 하거나(역호환성), + 또는 "jta"로 설정되도록 하라. + + + + getCurrentSession() 오퍼레이션들은 JTA 환경에서 한 가지 단점을 갖고 있다. + 디폴트로 사용되는, after_statement 커넥션 해제 모드 사용에 대한 하나의 보류 통보가 존재한다. + JTA 명세서의 어리석은 제한으로 인해, Hibernate가 scroll() 또는 iterate()에 + 의해 반환되는 임의의 닫혀지지 않은 ScrollableResults 또는 Iterator + 인스턴스들을 자동적으로 제거하는 것이 불가능하다. 당신은 finally 블록 내에서 명시적으로 + ScrollableResults.close() 또는 Hibernate.close(Iterator)를 + 호출하여 기본 데이터베이스 커서를 해제시켜야 한다.(물론 대부분의 어플리케이션들은 JTA 또는 CMT 코드에서 + scroll()이나 iterate()를 사용하는 것을 쉽게 피할 수 있다.) @@ -615,9 +621,7 @@ try { sess.getTransaction().commit() } catch (RuntimeException e) { - if ( sess.getTransaction().isActive() ) { sess.getTransaction().rollback(); - } throw e; // or display error message } finally { @@ -639,8 +643,8 @@ finally { 고도의 동시성과 고도의 가용성을 일치시키는 유일한 접근법은 버전화를 가진 optimistic동시성 제어이다. 버전 체킹은 업데이트 충돌을 검출하기 위해(그리고 업데이트 손실을 방지하기 위해) 버전 번호들 또는 timestamp들을 사용한다. Hibernate는 optimistic 동시성을 - 사용하는 어플리케이션 코드 작성에 세 가지 가능한 접근법들을 제공한다. 우리가 보여주는 쓰임새들은 긴 어플리케이션 트랜잭션들의 상황 - 속에 있지만 버전 체킹 또한 단일 데이터베이스 트랜잭션들에서 업데이트 손실을 방지하는 이점을 갖고 있다. + 사용하는 어플리케이션 코드 작성에 세 가지 가능한 접근법들을 제공한다. 우리가 보여주는 쓰임새들은 장시간의 대화의 상황 + 속에 있지만, 버전 체킹 또한 단일 데이터베이스 트랜잭션들에서 업데이트 손실을 방지하는 이점을 갖고 있다. @@ -649,16 +653,18 @@ finally { 하나의 구현에서 Hibernate로부터 많은 도움이 없이, 데이터베이스에 대한 각각의 상호작용은 새로운 Session 내에서 일어나고, 개발자는 영속 인스턴스들을 처리하기 전에 데이터베이스로부터 모든 영속 인스턴스들을 다시 로드시킬 책임이 있다. - 이 접근법은 어플리케이션 트랜잭션을 확실히 격리시키기 위해 그것 자신의 버전 체킹을 수행하도록 어플리케이션에게 강제시킨다. + 이 접근법은 대화 트랜잭션을 확실히 격리시키기 위해 그것 자신의 버전 체킹을 수행하도록 어플리케이션에게 강제시킨다. @@ -669,27 +675,31 @@ session.close();]]> 물론, 당신이 낮은 데이터 동시성 환경에서 작업하고 있고 버전 체킹을 필요로 하지 않을 경우에, 당신은 이 접근법을 사용할 수 도 있고 - 단지 버전 체크를 생략할 수도 있다. 그 경우에, 마지막의 커밋 성공은 당신의 긴 어플리케이션 트랜잭션들에 + 단지 버전 체크를 생략할 수도 있다. 그 경우에, 마지막의 커밋 성공은 당신의 장시간의 대화에 대한 디폴트 방도가 될 것이다. 이것이 어플리케이션의 사용자들을 혼동시킬 수 있음을 염두에 두라. 왜냐하면 사용자들은 오류 메시지들 또는 충돌 변경들을 병합시킬 기회 없이 업데이트들 손실을 겪을 수도 있기 때문이다. 명료하게 수작업 버전 체킹은 매우 사소한 환경들에서도 공포적이고 대부분의 어플리케이션들에 대해 실제적이지 않다. 흔히 단일 - 인스턴스 뿐만 아니라 변경된 객체들의 전체 그래프들이 체크되어야 한다. Hibernate는 설계 패러다임으로서 긴 Session + 인스턴스 뿐만 아니라 변경된 객체들의 전체 그래프들이 체크되어야 한다. Hibernate는 설계 패러다임으로서 하나의 확장된 Session 또는 detached 인스턴스들에 대해 자동적인 버전 체킹을 제공한다. - 긴 세션과 자동적인 버전화 + 확장된 세션과 자동적인 버전화 하나의 Session 인스턴스와 그것의 영속 인스턴스들은 전체 어플리케이션 트랜잭션에 사용된다. Hibernate는 flush 할 때 인스턴스 버전들을 체크하고 만일 동시성 변경이 검출될 경우에 예외상황을 던진다. 이 예외상황을 잡아내고 처리하는 것을 개발자의 몫이다(공통된 옵션들은 변경들을 병합시키거나 또는 쓸모가 없지 않은 데이터로 비지니스 프로세스를 다시 시작하는 기회를 사용자에게 주는 것이다). + 하나의 Session 인스턴스와 그것의 영속 인스턴스들은 session-per-conversation로 + 알려진 전체 대화에 사용된다. Hibernate는 flush 시점에서 인스턴스 버전들을 체크하며, 만일 동시적인 변경이 검출될 경우에 + 하나의 예외상황을 던진다. 이 예외상황을 포착하고 처리하는 것은 개발자의 몫이다(공통된 옵션들은 사용자가 변경들을 병합하거나 + 손실되지 않은 데이터를 가지고 비지니스 대화를 재시작하는 기회이다). @@ -698,40 +708,52 @@ session.close();]]> 그 자체 관계할 필요가 없거나 그것은 모든 데이터베이스 트랜잭션에서 인스턴스들을 다시 로드시킬 필요가 없다. - + +session.flush(); // Only for last transaction in conversation +t.commit(); // Also return JDBC connection +session.close(); // Only for last transaction in conversation]]> - foo 객체는 그것이 로드되었던 Session이 어느 것인지를 여전히 알고 있다. - Session.reconnect()은 새로운 커넥션을 획득하고(또는 당신이 커넥션을 제공할 수 있다) 그리고 - 그 세션을 다시 시작시킨다. Session.disconnect() 메소드는 JDBC 커넥션으로부터 세션을 - 연결 해제하고 (당신이 커넥션을 제공하지 않는 한) 그 커넥션을 풀(pool)로 반환할 것이다. 재연결 후에, 당신이 업데이트하고 - 있는 데이터에 대한 버전 체킹을 강제시키기 위해, 당신은 또 다른 트랜잭션에 의해 업데이트 되었던 어떤 객체들에 대해 - LockMode.READ로서 Session.lock()을 호출할 수도 있다. 당신은 당신이 - 업데이트 중인 어떤 데이터에 대한 잠금을 필요로 하지 않는다. + foo 객체는 그것이 로드되었던 Session이 어느 것인지를 여전히 알고 있다. + 이전 세션 상에서 하나의 새로운 데이터베이스 트랜잭션을 시작하는 것은 하나의 새로운 커넥션을 획득하고 그 세션을 소비한다. + 데이터베이스 트랜잭션을 커밋(확약)시키는 것은 그 JDBC 커넥션으로부터 하나의 세션을 연결해제시키고 그 커넥션을 풀(pool)로 + 반환시킬 것이다. 재연결 후에, 당신이 업데이트하고 있지 않은 데이터에 대한 버전 체크를 강제시키기 위해서, 당신은 + 또 다른 트랜잭션에 의해 업데이트되었을 수도 있는 임의의 객체들에 대해 LockMode.READ로서 + Session.lock()을 호출할 수도 있다. 당신은 당신이 업데이트 중인 임의의 데이터를 잠금할 필요가 없다. + 대개 당신은 마지막 데이터베이스 트랜잭션 주기만이 이 대화 내에서 행해진 모든 변경들을 실제로 영속화시키는 것이 허용되도록 하기 위해, + 하나의 확장된 Session에 대해 FlushMode.NEVER를 설정할 것이다. + 그러므로 오직 이 마지막 데이터베이스 트랜잭션 만이 flush() 오퍼레이션을 포함할 것이고, 또한 + 대화를 종료시키기 위해 세션을 close()할 것이다. - - 만일 disconnect()reconnect()에 대한 명시적인 호출들이 너무 번거러울 경우, - 당신은 대신에 hibernate.connection.release_mode를 사용할 수도 있다. - - - - 만일 사용자가 생각하는시간 동안 Session이 저장되기에는 너무 큰 경우 이 패턴은 문제성이 있다. 예를 들어 + 만일 사용자가 생각하는시간 동안 Session이 저장되기에 너무 큰 경우 이 패턴은 문제성이 있다. 예를 들어 HttpSession은 가능한 작은 것으로 유지되어야 한다. 또한 Session은 (필수의) - 첫 번째 레벨 캐시이고 모든 로드된 객체들을 포함하기 때문에, 우리는 아마 적은 요청/응답 주기들에 대해서만 이 방도를 사용할 수 있다. - Session이 곧 실효성이 없는 데이터를 갖게 될 것이므로 이것이 진정으로 권장된다. + 첫 번째 레벨 캐시이고 모든 로드된 객체들을 포함하기 때문에, 우리는 아마 적은 요청/응답 주기들에 대해서만 이 방도를 사용할 수 있다. + 당신은 하나의 대화에 대해서만 하나의 Session을 사용해야 한다. 왜냐하면 그것은 또한 곧 실없는 데이터가 + 될 것이기 때문이다. - 또한 당신이 연결해제된 Session을 영속 계층에 가깝게 유지해야함을 노트하라. 달리말해, - Session을 보관하는데 EJB stateful session bean을 사용하고 HttpSession - 내에 그것을 저장하기 위해서 그것을 웹 계층에 전송하지 말라(또는 그것을 별도의 티어에 직렬화 시키지도 말라). + (초기의 Hibernate 버전들은 Session에 대한 명시적인 연결해제와 재연결을 필요로 했음을 + 노트하라. 트랜잭션을 시작하고 끝내는 것이 동일한 효과를 가지므로, 이들 방법들은 진부하게 되었다.) + + + + 또한 당신은 영속 계층에 대해 연결해제된 Session을 닫혀진채로 유지해야함을 노트하라. 달 + 리말해, 하나의 3-tier 환경에서 Session을 소유하는데 EJB stateful session bean을 + 사용하고, HttpSession 내에 그것을 저장하기 위해 그것을 웹 계층에 전송하지 말라 + (또는 그것을 별도의 티어에 직렬화 시키지도 말라). + + + + 확장된 세션 패턴, 또는 session-per-conversation은 자동적인 현재 세션 컨텍스트 관리에 대해 + 구현하기가 더 어렵다. 당신은 이를 위해 당신 자신의 CurrentSessionContext 구현을 공급할 필요가 + 있으며, 예제들은 Hibernate Wiki를 보라. @@ -900,6 +922,87 @@ session.close();]]> + + + 연결 해제 모드들 + + + JDBC 커넥션 관리에 관한 Hibernate의 리거시(2.x) 특징은 그것이 처음으로 필요로 했을 때 + 하나의 Session이 하나의 커넥션을 획득할 것이고, 그런 다음 그 커넥션은 그 세션이 + 닫혀질때까지 보관된다는 것이었다. + Hibernate 3.x는 세션에게 그것의 JDBC 커넥션들을 처리하는 방법을 알려주기 위해 연결 해제 모드들에 관한 + 개념을 도입했다. 다음 논의는 구성된 ConnectionProvider를 통해 제공되는 커넥션들에 + 대해서만 적절하다는 점을 노트하라; 사용자가 제공하는 커넥션들은 + org.hibernate.ConnectionReleaseMode의 열거된 값들에 의해 식별된다: + + + + + + ON_CLOSE - 는 본질적으로 위에 설명된 리거시 특징이다. Hibernate 세션은 그것이 + 어떤 JDBC 접근을 수행하고 세션이 닫혀질 때까지 그 커넥션을 보관할 필요가 있을 때 하나의 커넥션을 획득한다. + + + + + AFTER_TRANSACTION - 은 하나의 + org.hibernate.Transaction이 완료된 후에 연결들을 해제하라고 말한다. + + + + + AFTER_STATEMENT (또한 적극적인 해제라고 언급됨) - 는 각각의 모든 문장 실행 후에 + 커넥션들을 해제하라고 말한다. 이 적극적인 해제는 그 문장이 주어진 세션과 연관된 리소스들을 열려진채로 남겨둘 + 경우에는 건너뛰게(skip) 된다; 현재 이것이 일어나는 유일한 상황은 + org.hibernate.ScrollableResults의 사용을 통해서이다. + + + + + + 사용할 해제 모드를 지정하기 위해 구성 파라미터 hibernate.connection.release_mode가 사용된다. + 가능한 값들은 다음과 같다: + + + + + + auto (디폴트) - 이 선택은 + org.hibernate.transaction.TransactionFactory.getDefaultReleaseMode() + 메소드에 의해 반환된 해제 모드로 위임시킨다. JTATransactionFactory인 경우, 이것은 + ConnectionReleaseMode.AFTER_STATEMENT를 반환한다; JDBCTransactionFactory인 경우, 이것은 + ConnectionReleaseMode.AFTER_TRANSACTION을 반환한다. 이 설정의 값이 사용자 코드 내의 버그들 그리고/또는 + 유효하지 않은 가정들을 가리키는 경향이 있음으로 인해 이 디폴트 특징을 실패로 변경하는 것은 거의 좋은 생각이 아니다. + + + + + on_close - 는 ConnectionReleaseMode.ON_CLOSE를 사용하라고 말한다. 이 설정은 + 역호환성을 위해 남겨졌지만, 그것의 사용은 매우 권장되지 않는다. + + + + + after_transaction - 은 ConnectionReleaseMode.AFTER_TRANSACTION을 사용하라고 말한다. + 이 설정은 JTA 환경들에서 사용되지 않을 것이다. 또한 + ConnectionReleaseMode.AFTER_TRANSACTION인 경우에 만일 세션이 auto-commit 모드에 있도록 고려될 경우, + 커넥션들은 마치 해제 모드가 AFTER_STATEMENT인 것처럼 해제될 것임을 또한 노트하라. + + + + + after_statement - 는 ConnectionReleaseMode.AFTER_STATEMENT를 사용하라고 말한다. + 추가적으로 구성된 ConnectionProvider는 그것이 이 설정 + (supportsAggressiveRelease())을 지원하는지 여부를 알기 위해 참고된다. + 만일 지원하지 않을 경우, 해제 모드는 ConnectionReleaseMode.AFTER_TRANSACTION으로 재설정된다. 이 설정은 + 우리가 ConnectionProvider.getConnection()을 호출할 때마다 우리가 동일한 기본 JDBC + 커넥션을 다시 필요로 할 수 있는 환경들에서 또는 우리가 동일한 커넥션을 얻는 것에 상관없는 auto-commit 환경에서 오직 + 안전하다. + + + + + diff --git a/reference/ko/modules/tutorial.xml b/reference/ko/modules/tutorial.xml index 3639534ea4..24c6f635a9 100644 --- a/reference/ko/modules/tutorial.xml +++ b/reference/ko/modules/tutorial.xml @@ -17,7 +17,7 @@ - + 파트 1 - 첫 번째 Hibernate 어플리케이션 @@ -26,7 +26,7 @@ - 우리가 우리가 출석을 원하는 이벤트들을 저장할 수 있는 작은 데이터베이스 어플리케이션과 이들 + 우리가 우리가 수반하고자 원하는 이벤트들을 저장할 수 있는 작은 데이터베이스 어플리케이션과 이들 이벤트들의 호스트들에 대한 정보를 필요로 한다고 가정하자. @@ -40,7 +40,7 @@ - 이것은 Hibernate에 필요한 최소한의 세트이다(우리는 또한 메인 아카이브인 hibernate3.jar를 - 복사했음을 노트하라). 필수적인 제 3의 라이브러리와 선택적인 제 3의 라이브러리들에 대한 추가 정보는 - Hibernate 배포본의 lib/ 디렉토리 속에 있는 README.txt 파일을 보라. - (실제로, Log4j는 필수적이지는 않지만 많은 개발자들에 의해 선호된다.) + 이것은 글의 작성 시점에서 Hibernate에 필수적인 최소한의 세트이다(우리는 + 또한 메인 아카이브인 hibernate3.jar를 복사했음을 노트하라). 당신이 사용 중인 Hibernate 배포본이 + 더 많거나 보다 적은 라이브러리들을 필요로 할 수도 있다. 필수 라이브러리들과 선택적인 제3의 라이브러리들에 대한 + 추가 정보는 Hibernate 배포본의 lib/ 디렉토리 내에 있는 README.txt + 파일을 보라. (실제로, Log4j는 필수는 아니지만 많은 개발자들에 의해 선호된다.) @@ -285,7 +286,7 @@ public class Event { - + Hibernate 구성 @@ -297,7 +298,12 @@ public class Event { 개발 디렉토리의 루트에 data로 명명된 디렉토리를 생성시켜라 - 이 디렉토리는 - HSQL DB가 그것의 데이터 파일들을 저장하게 될 장소이다. + HSQL DB가 그것의 데이터 파일들을 저장하게 될 장소이다. 이제 이 데이터 디렉토리에서 + java -classpath lib/hsqldb.jar org.hsqldb.Server를 실행시켜서 + 데이터베이스를 시작시켜라. 당신은 그것이 시작되고 이것은 우리의 어플리케이션이 나중에 연결하게 될 장소인, + 하나의 TCP/IP 소켓에 바인드 되는 것을 볼 수 있다. 만일 이 튜토리얼 동안에 당신이 새 데이터베이스로 + 시작하고자 원할 경우, HSQL DB를 셧다운시키고(왼도우에서 CTRL + C를 눌러라), + data/ 디렉토리 내에 있는 모든 파일들을 삭제하고 다시 HSQL DB를 시작하라. @@ -802,19 +808,19 @@ else if (args[0].equals("list")) { - + 단방향 Set-기반의 연관 우리는 Person 클래스에 이벤트들을 가진 한 개의 콜렉션을 추가할 것이다. 그 방법으로 우리는 - 명시적인 질의를 실행시키지 않고서 -aPerson.getEvents()를 호출하여- 특정 개인에 대한 - 이벤트들을 쉽게 네비게이트할 수 있다. 우리는 하나의 Java 콜렉션, Set를 사용한다. 왜냐하면 - 그 콜렉션은 중복 요소들을 포함하기 않을 것이고 그 순서가 우리와 관련되어 있지 않기 때문이다. + 명시적인 질의-aPerson.getEvents()를 호출함으로써-를 실행시키지 않고서 특정 개인에 대한 + 이벤트들을 쉽게 네비게이트할 수 있다. 우리는 하나의 Java 콜렉션, 하나의 Set를 사용한다. 왜냐하면 + 그 콜렉션은 중복 요소들을 포함하기 않을 것이고 그 순서가 우리와 관련되어 있지 않기 때문이다. - 지금까지 우리는 Set으로 구현된 단방향이고 다중 값을 가진 연관들을 설계했다. - Java 클래스들 속에 이를 위한 코드를 작성하고 그런 다음 그것을 매핑시키자: + 우리는 하나의 Set으로 구현된, 하나의 단방향, 다중값 연관들을 필요로 한다. Java 클래스들 내에 + 이를 위한 코드를 작성하고 그런 다음 그것을 매핑시키자: - + + + + 이 연관을 매핑시키기 전에, 다른 측에 대해 생각해보자. 명료하게 우리는 이것을 단방향으로 유지시킬 수 있다. 또는 + 만일 우리가 양방향으로 네비게이트하는 것을 가능하도록 하고자 원할 경우에, 우리는 Event 상의 + 또 다른 콜렉션을 생성시킬 수 있다. 예를 들면.anEvent.getParticipants(). 이것은 + 기능적인 관점에서 필수적이지 않다. 당신은 특정 이벤트에 대한 참여자들을 검색하기 위해 하나의 명시적인 질의를 항상 + 실행시킬 수 있다. 이것은 당신에게 설계상의 선택으로 남겨두지만, 이 논의에서 명료해지는 것은 그 연관의 다중성이다: + 양 측들이 "many" 값을 가질 경우, 우리는 이것을 many-to-many 연관이라 명명한다. 그러므로, + 우리는 Hibernate의 many-to-many 매핑을 사용한다: + + + - + @@ -849,19 +878,18 @@ else if (args[0].equals("list")) { - + ]]> - Hibernate는 모든 종류의 콜렉션 매핑들, 가장 공통적인 <set>을 지원한다. many-to-many - 연관 (또는 n:m 엔티티 관계)의 경우, 한 개의 연관 테이블이 필요하다. 이 테이블 속에 있는 각각의 + 연관 (또는 n:m 엔티티 관계)의 경우, 한 개의 연관 테이블이 필요하다. 이 테이블 내에 있는 각각의 행은 한 명의 개인과 한 개의 이벤트 사이의 링크를 표현한다. 테이블 이름은 set 요소의 table 속성으로 구성된다. 연관 내의 식별자 컬럼 이름은 개인 측에 대해 <key> 요소로 정의되고 이벤트 측에 대한 컬럼 이름은 <many-to-many>column 속성으로 정의된다. 당신은 또한 당신의 콜렉션 내에 있는 객체들의 클래스(정확하게 : 참조들을 가진 콜렉션의 다른 측 상에 있는 클래스)를 - Hibernate에게 알려주어야 한다 + Hibernate에게 알려주어야 한다. @@ -1136,20 +1164,273 @@ public void removeFromEvent(Event event) { 모든 양방향 연관들은 한 쪽이 inverse일 필요가 있다. one-to-many 연관에서 그것은 many-측이어야 하고, many-to-many 연관에서 당신은 어느 측이든 선택할 수 있으며 차이점은 없다. - + + + + + dateFormatter는 나중에 문자열들로부터 그리고 문자열로 Date 객체들을 + 변환하는데 나중에 사용하게 될 도구이다. 서블릿의 멤버로서 오직 한 개의 formatter를 갖는 것이 도리에 맞다. + + + + 서블릿은 HTTP GET 요청들 만을 처리하므로, 우리가 구현하는 메소드는 doGet()이다: + + + + + + 우리가 여기서 적용하는 패턴은 session-per-request이다. 하나의 요청이 + 서블릿에 도달할 때, 하나의 새로운 Hibernate Session이 + SessionFactory 상의 getCurrentSession()에 대한 + 첫번째 호출을 통해 열린다. 그때 하나의 데이터베이스 트랜잭션이 시작되고, 모든 데이터 접근이 하나의 트랜잭션 + 내에서 발생하는 한, 데이터가 읽혀지거나 기록되는데 문제가 없다(우리는 어플리케이션들 내에서 auto-commit 모드를 + 사용하지 않는다). + + + + 다음으로, 요청의 가능한 액션들이 처리되고 응답 HTML이 렌더링된다. 우리는 곧장 그부분으로 갈 것이다. + + + + 마지막으로, 프로세싱과 렌더링이 완료될 때 작업 단위가 종료된다. 만일 어떤 문제가 프로세싱과 렌더링 동안에 발생될 경우, + 하나의 예외상황이 던져질 것이고 데이터베이스 트랜잭션은 롤백될 것이다. 이것은 session-per-request을 + 완료시킨다. 모든 서블릿 내에 있는 트랜잭션 구획 코드 대신에 당신은 또한 서블릿 필터를 사용할 수 있다. + Open Session in View로 명명되는 이 패턴에 대한 추가 정보는 Hibernate 웹 사이트와 위키를 보라. + 당신은 서블릿 내에서가 아닌 JSP 내에 당신의 뷰를 렌더링하는 것을 고려할 때 그것을 필요로 할 것이다. + + + + + + 프로세싱과 렌더링 + + + 요청의 처리와 페이지의 렌더링을 구현하자. + + +Event Manager"); + +// Handle actions +if ( "store".equals(request.getParameter("action")) ) { + + String eventTitle = request.getParameter("eventTitle"); + String eventDate = request.getParameter("eventDate"); + + if ( "".equals(eventTitle) || "".equals(eventDate) ) { + out.println("Please enter event title and date."); + } else { + createAndStoreEvent(eventTitle, dateFormatter.parse(eventDate)); + out.println("Added event."); + } +} + +// Print page +printEventForm(out); +listEvents(out); + +// Write HTML footer +out.println(""); +out.flush(); +out.close();]]> + + + Java와 HTML이 혼합된 이 코딩이 보다 복잡한 어플리케이션에서 기준이 될 수 없다 할지라도, 우리는 + 단지 이 튜토리얼 내에서 기본 Hibernate 개념들을 설명하고 있음을 염두에 두라. 코드는 + 하나의 HTML 헤더와 하나의 footer를 프린트한다. 이 페이지 내에 이벤트 엔트리를 위한 + 하나의 HTML form과 데이터베이스 내에 있는 모든 이벤트들의 목록이 프린트된다. 첫 번째 메소드는 + 시행적이고 오직 HTML을 출력한다: + + + Add new event:"); + out.println("
"); + out.println("Title:
"); + out.println("Date (e.g. 24.12.2009):
"); + out.println(""); + out.println(""); +}]]>
+ + + listEvents() 메소드는 하나의 질의를 실행하기 위해서 현재의 + 쓰레드에 결합된 Hibernate Session을 사용한다: + + + 0) { + out.println("

Events in database:

"); + out.println("
"); + out.println(""); + out.println(""); + out.println(""); + out.println(""); + for (Iterator it = result.iterator(); it.hasNext();) { + Event event = (Event) it.next(); + out.println(""); + out.println(""); + out.println(""); + out.println(""); + } + out.println("
Event titleEvent date
" + event.getTitle() + "" + dateFormatter.format(event.getDate()) + "
"); + } +}]]> + + + 마지막으로, store 액션은 createAndStoreEvent() + 메소드로 디스패치된다. 그것은 현재 쓰레드의 Session을 사용한다: + + + + + + 즉 서블릿이 완성된다. 서블릿에 대한 요청은 하나의 단일 Session과 + Transaction 내에서 처리될 것이다. 이전처럼 스탠드얼론 어플리케이션에서, + Hibernate는 이들 객체들을 실행 중인 현재 쓰레드에 자동적으로 바인드시킬 수 있다. 이것은 당신의 코드를 + 계층화 시키고 당신이 좋아하는 임의의 방법으로 SessionFactory에 접근하는 자유를 + 당신에게 부여한다. 대개 당신은 보다 세련된 설계를 사용할 것이고 데이터 접근 코드를 데이터 접근 객체들 내로 + 이동시킬 것이다(DAO 패턴). 추가 예제들은 Hibernate 위키를 보라. + + + + + + 배치하기 그리고 테스트하기 + + + 이 어플리케이션을 배치하기 위해서 당신은 하나의 웹 아카이브, WAR를 생성시켜야 한다. 다음 Ant target을 + 당신의 build.xml 내에 추가하라: + + + + + + + + + + +]]> + + + 이 target은 당신의 프로젝트 디렉토리 내에 hibernate-tutorial.war로 명명된 + 하나의 파일을 생성시킨다. 그것은 당신의 프로젝트의 기본 디렉토리 내에 기대되는 모든 라이브러리들과 + web.xml 디스크립터를 패키징한다: + + + + + + + Event Manager + events.EventManagerServlet + + + + Event Manager + /eventmanager + +]]> + + + 당신이 웹 어플리케이션을 컴파일하고 배치하기 전에, 하나의 부가적인 라이브러리가 필요함을 노트하라: + jsdk.jar. 당신이 이미 이 라이브러리를 갖고 있지 않을 경우, 이것은 Java servlet + development kit이며, Sun 웹 사이트로부터 그것을 얻어서 그것을 당신의 라이브러리 디렉토리에 복사하라. + 하지만 그것은 오직 컴파일 시에만 사용될 것이고 WAR 패키지에서는 제외된다. + + + + 빌드하고 배치하기 위해 당신의 프로젝트 디렉토리 내에서 ant war를 호출하고 + hibernate-tutorial.war 파일을 당신의 Tomcat webapp + 디렉토리로 복사하라. 만일 당신이 Tomcat을 설치하지 않았다면, 그것을 내려받아 설치 지침들을 따르라. 당신은 + 이 어플리케이션을 배치하기 위해 임의의 Tomcat 구성을 변경하지 않아야 한다. + + + + 일단 배치했고 Tomcat이 실행중이면, http://localhost:8080/hibernate-tutorial/eventmanager로 + 어플리케이션에 접근하라. 첫 번째 요청이 당신의 서블릿에 도달할 때 Hibernate가 초기화(HibernateUtil + 내에 있는 static initializer가 호출된다) 되는 것을 보기 위해 그리고 만일 어떤 예외상황들이 발생할 경우 + 상세한 출력을 얻기 위해서 Tomcat 로그를 지켜보도록 하라. + +
- + 요약 - 이 튜토리얼은 간단한 스탠드얼론 Hibernate 어플리케이션을 작성하는 기초를 다루었다. + 이 튜토리얼은 간단한 스탠드얼론 Hibernate 어플리케이션과 하나의 작은 웹 어플리케이션을 작성하는 기초를 다루었다.