diff --git a/reference/build.xml b/reference/build.xml
index 816eaef45c..5b46faeae6 100644
--- a/reference/build.xml
+++ b/reference/build.xml
@@ -28,6 +28,7 @@
+
@@ -37,6 +38,7 @@
+
diff --git a/reference/ko/fop/Gaeul.ttf b/reference/ko/fop/Gaeul.ttf
new file mode 100644
index 0000000000..05f667f965
Binary files /dev/null and b/reference/ko/fop/Gaeul.ttf differ
diff --git a/reference/ko/fop/Gaeul.xml b/reference/ko/fop/Gaeul.xml
new file mode 100644
index 0000000000..a796ceeebd
--- /dev/null
+++ b/reference/ko/fop/Gaeul.xml
@@ -0,0 +1 @@
+가을체00858-141-16-14810008853300TYPE0CIDFontType20
\ No newline at end of file
diff --git a/reference/ko/fop/Gulim.xml b/reference/ko/fop/Gulim.xml
new file mode 100644
index 0000000000..42a8beadc8
--- /dev/null
+++ b/reference/ko/fop/Gulim.xml
@@ -0,0 +1 @@
+Gulim00858-1410-15010008633300GulimTYPE0CIDFontType20
\ No newline at end of file
diff --git a/reference/ko/fop/gulim.ttc b/reference/ko/fop/gulim.ttc
new file mode 100644
index 0000000000..04747c3ccb
Binary files /dev/null and b/reference/ko/fop/gulim.ttc differ
diff --git a/reference/ko/fop/userconfig.xml b/reference/ko/fop/userconfig.xml
new file mode 100644
index 0000000000..be63f380fe
--- /dev/null
+++ b/reference/ko/fop/userconfig.xml
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/reference/ko/images/AuthorWork.gif b/reference/ko/images/AuthorWork.gif
new file mode 100644
index 0000000000..d0fb5125fa
Binary files /dev/null and b/reference/ko/images/AuthorWork.gif differ
diff --git a/reference/ko/images/AuthorWork.zargo b/reference/ko/images/AuthorWork.zargo
new file mode 100644
index 0000000000..f249b22951
Binary files /dev/null and b/reference/ko/images/AuthorWork.zargo differ
diff --git a/reference/ko/images/CustomerOrderProduct.gif b/reference/ko/images/CustomerOrderProduct.gif
new file mode 100644
index 0000000000..52d84864d5
Binary files /dev/null and b/reference/ko/images/CustomerOrderProduct.gif differ
diff --git a/reference/ko/images/CustomerOrderProduct.zargo b/reference/ko/images/CustomerOrderProduct.zargo
new file mode 100644
index 0000000000..016c559eee
Binary files /dev/null and b/reference/ko/images/CustomerOrderProduct.zargo differ
diff --git a/reference/ko/images/EmployerEmployee.gif b/reference/ko/images/EmployerEmployee.gif
new file mode 100644
index 0000000000..112e9b4f08
Binary files /dev/null and b/reference/ko/images/EmployerEmployee.gif differ
diff --git a/reference/ko/images/EmployerEmployee.zargo b/reference/ko/images/EmployerEmployee.zargo
new file mode 100644
index 0000000000..487368e8c7
Binary files /dev/null and b/reference/ko/images/EmployerEmployee.zargo differ
diff --git a/reference/ko/images/full_cream.gif b/reference/ko/images/full_cream.gif
new file mode 100644
index 0000000000..ef15d69100
Binary files /dev/null and b/reference/ko/images/full_cream.gif differ
diff --git a/reference/ko/images/full_cream.svg b/reference/ko/images/full_cream.svg
new file mode 100644
index 0000000000..d62b66e893
--- /dev/null
+++ b/reference/ko/images/full_cream.svg
@@ -0,0 +1,429 @@
+
+
+]>
+
+
diff --git a/reference/ko/images/hibernate_logo_a.png b/reference/ko/images/hibernate_logo_a.png
new file mode 100644
index 0000000000..0a343c4bca
Binary files /dev/null and b/reference/ko/images/hibernate_logo_a.png differ
diff --git a/reference/ko/images/lite.gif b/reference/ko/images/lite.gif
new file mode 100644
index 0000000000..fd34bcec09
Binary files /dev/null and b/reference/ko/images/lite.gif differ
diff --git a/reference/ko/images/lite.svg b/reference/ko/images/lite.svg
new file mode 100644
index 0000000000..747d34e185
--- /dev/null
+++ b/reference/ko/images/lite.svg
@@ -0,0 +1,334 @@
+
+
+]>
+
+
diff --git a/reference/ko/images/overview.gif b/reference/ko/images/overview.gif
new file mode 100644
index 0000000000..d7dfda915c
Binary files /dev/null and b/reference/ko/images/overview.gif differ
diff --git a/reference/ko/images/overview.svg b/reference/ko/images/overview.svg
new file mode 100644
index 0000000000..7ec1c26be7
--- /dev/null
+++ b/reference/ko/images/overview.svg
@@ -0,0 +1,250 @@
+
+
+]>
+
+
diff --git a/reference/ko/images/tutorial_schema.GIF b/reference/ko/images/tutorial_schema.GIF
new file mode 100644
index 0000000000..7f7db2f250
Binary files /dev/null and b/reference/ko/images/tutorial_schema.GIF differ
diff --git a/reference/ko/master.xml b/reference/ko/master.xml
new file mode 100644
index 0000000000..2eac108502
--- /dev/null
+++ b/reference/ko/master.xml
@@ -0,0 +1,191 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]>
+
+
+
+
+ HIBERNATE - 개성있는 자바를 위한 관계 영속
+ 하이버네이트 참조 문서
+ 3.0.5
+
+
+
+
+
+ 머리말
+
+
+ 객체 지향 소프트웨어와 관계형 데이터베이스로 작업하는 것은 오늘날의 엔터프라이즈 환경들에서 성가시고 시간이
+ 소비될 수 있다. Hibernate는 자바 환경들을 위한 객체/관계형 매핑 도구이다.
+ object/relational mapping(ORM) 용어는 객체 모형으로부터 SQL-기반의 스키마를 가진
+ 관계형 데이터 모형으로의 데이터 표상을 매핑하는 기술을 언급한다.
+
+
+
+ Hibernate는 자바 클래스들로부터 데이터베이스로의 매핑(그리고 자바 데이터 타입들로부터 SQL 데이터
+ 타입들로의 매핑)을 처리할 뿐만 아니라, 또한 데이터 질의와 검색 편의들을 제공하며, SQL과 JDBC로
+ 수작업 데이터 핸들링에 소요되는 개발 시간을 현저하게 단축시켜줄 수 있다.
+
+
+
+ Hibernate의 목적은 공통된 데이터 영속화 관련 프로그래밍 작업들의 95%를 덜어주는 것이다.
+ Hibernate는 데이터베이스에서 비지니스 로직을 구현하는데 내장 프로시저들을 전용으로 사용하는 데이터
+ 중심적 어플리케이션에 대한 최상의 솔루션이 아닐 수도 있지만, 그것은 자바 기반 미들-티어에서 객체 지향
+ 도메인 모형들과 비지니스 로직에 가장 유용하다. 하지만 Hibernate는 벤더 지정적인 SQL 코드를
+ 제거하거나 캡슐화 시키는 당신을 확실히 도와줄 수 있고 테이블 형식의 표현으로부터 객체들의 그래프로 결과
+ 셋을 변환하는 공통된 태스크를 도와줄 것이다.
+
+
+
+ 만일 당신이 Hibernate와 Object/Relational 매핑 또는 심지어 자바에 초심자라면, 다음
+ 단계들을 따르기 바란다:
+
+
+
+
+
+ Tomcat을 사용하는 30분짜리 빠른시작,
+
+ 을 읽어라.
+
+
+
+
+ 더 많은 단계적인 사용 설명서들을 가진 더 긴 튜토리얼은
+
+ 을 읽어라.
+
+
+
+
+ Hibernate가 사용될 수 있는 환경을 이해려면
+
+ 를 읽어라.
+
+
+
+
+ Hibernate 배포본 내의
+ eg/
+ 디렉토리를 살펴 보라. 이 디렉토리는 간단한 스탠드얼론 어플리케이션을 포함하고 있다. 당신의
+ JDBC 드라이버를
+ lib/
+ 디렉토리에 복사하고 당신의 데이터베이스에 맞는 정확한 값을 지정하여
+ etc/hibernate.properties
+ 를 편집하라. 배보본 디렉토리에서 명령 라인 프롬프트에서 (Ant를 사용하여)
+ ant eg
+ 를 타이핑 하거나 , Windows 하에서
+ build eg
+ 를 타이프 하라.
+
+
+
+
+ 당신의 주된 정보의 소스로서 이 참조 문서를 사용하라. 만일 어플리케이션 설계에 대해 더 많은
+ 도움을 필요로 하거나 당신이 단계적인 튜토리얼을 선호한다면
+ Hibernate in Action
+ (http://www.manning.com/bauer)을 읽는 것을 고려하라.또한
+ http://caveatemptor.hibernate.org에 방문하여 Hibernate in
+ Action용 예제 어플리케이션을 다운로드 하라.
+
+
+
+ FAQ들은 Hibernate 웹 사이트 상에 답변되어 있다.
+
+
+
+ 제 3의 데모들, 예제들, 그리고 튜토리얼들은 Hibernate 웹 사이트 상에 링크되어
+ 있다.
+
+
+
+
+ Hibernate 웹사이트 상의 공동체 영역은 설계 패턴과 다양한 통합 솔루션들(Tomcat,
+ JBoss AS, Struts, EJB 등.)에 관한 좋은 리소스이다.
+
+
+
+
+
+ 질문이 있다면, Hibernate 상에 링크되어 있는 사용자 포럼을 사용하라. 우리는 또한 버그 보고와 특징
+ 요청들을 위한 JIRA 쟁점 추적 시스템을 제공한다. 당신이 Hibernate의 개발에 관심이 있다면,
+ 개발자 메일링 리스트에 참여하라. 만일 당신이 이 문서를 당신의 언어로 번역하는 것에 관심이 있다면, 개발자
+ 메일링 리스트에 접촉하라.
+
+
+
+ Hibernate를 위한 상용 개발 지원, 제품 지원, 그리고 교육은 JBoss Inc를 통해 이용 가능하다
+ (http://www.hibernate.org/SupportTraining/를 보라). Hibernate는
+ JBoss Professional Open Source product 프로젝트이고 제품들에 대한 JBoss
+ Enterprise Middleware System (JEMS) suite의 중대한 컴포넌트이다.
+
+
+
+
+ &quickstart;
+
+ &tutorial;
+
+ &architecture;
+
+ &configuration;
+
+ &persistent-classes;
+
+ &basic-mapping;
+ &collection-mapping;
+ &association-mapping;
+ &component-mapping;
+ &inheritance-mapping;
+
+ &session-api;
+ &transactions;
+ &events;
+ &batch;
+
+ &query-hql;
+ &query-criteria;
+ &query-sql;
+ &filters;
+ &xml;
+
+ &performance;
+
+ &toolset-guide;
+
+ &example-parentchild;
+ &example-weblog;
+ &example-mappings;
+
+ &best-practices;
+
+
+
diff --git a/reference/ko/modules/architecture.xml b/reference/ko/modules/architecture.xml
new file mode 100644
index 0000000000..7b6b997994
--- /dev/null
+++ b/reference/ko/modules/architecture.xml
@@ -0,0 +1,240 @@
+
+
+ 아키텍처
+
+
+ 개요
+
+
+ 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 objects and collections
+
+
+ persistent 상태와 비지니스 기능을 포함하는 수명이 짧고, 단일 쓰레드인 객체들. 이것들은 통상의 JavaBeans/POJO들일
+ 수 있고, 오직 그것들에 대한 오직 특별한 것은 그것들이 현재 (정확하게 한 개의) Session과 연관되어
+ 있다는 점이다. Session이 닫히자마자, 그것들은 분리될(detached 상태가 될) 것이고 어플리케이션
+ 레이어에서 사용하는 것이 자유로와진다(예를 들면. 프리젠테이션으로의 데이터 전송 객체들로서 직접적으로 그리고 프리젠테이션으로부터
+ 데이터 전송 객체들로서 직접으로).
+
+
+
+
+ Transient and detached objects and collections
+
+
+ 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들을 무시한다.
+
+
+
+
+ 인스턴스 상태들
+
+ 영속 클래스들의 인스턴스는 세개의 상태들 중 하나 일 수 있다. 그것들(상태들)은 영속 컨텍스트(persistence context)에
+ 대해 정의된다. Hibernate Session 객체는 영속 컨텍스트이다:
+
+
+
+
+ transient
+
+
+ 인스턴스는 임의의 컨텍스트와 연관되어 있지 않고, 결코 연관된 적이 없었다. 그것은 영속 식별자(프라이머리 키 값)을 갖지 않는다.
+
+
+
+
+ persistent
+
+
+ 인스턴스는 현재 영속 컨텍스트와 연관되어 있다. 그것은 영속 식별자(프라이머리 키 값) 그리고 아마 데이터베이스 내에 있는 대응하는
+ 행을 갖는다. 특별한 영속 컨텍스트의 경우, Hibernate는 영속 identity가 Java identity(객체의 메모리 내 위치)와 같다는 점을
+ 보증한다.
+
+
+
+
+ detached
+
+
+ 인스턴스는 영속 컨텍스트와 한번 연관되었지만, 그 컨텍스트가 닫혔거나, 그 인스턴스가 또 다른 프로세스로 직렬화 되었다. 그것은 영속
+ identity 그리고, 아마 데이터베이스 내에 대응하는 행을 갖는다. detached 인스턴스들의 경우, Hibernate는 영속 identity과
+ Java identity 사이의 관계를 보증하지 않는다.
+
+
+
+
+
+
+
+ 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 통계이다.
+ 를 보라.
+
+
+
+
+ JCA 지원
+
+ Hibernate는 JCA 커넥터로서 구성될 수도 있다. 상세한 것은 웹 사이트를 보길 바란다. Hibernate JCA 지원은 여전히 실험적으로
+ 검토 중에 있음을 노트하길 바란다.
+
+
+
+
+
diff --git a/reference/ko/modules/association_mapping.xml b/reference/ko/modules/association_mapping.xml
new file mode 100644
index 0000000000..45892e0eb1
--- /dev/null
+++ b/reference/ko/modules/association_mapping.xml
@@ -0,0 +1,523 @@
+
+
+ 연관 매핑들
+
+
+ 개요
+
+
+ 연관 매핑들은 올바른 것을 얻기가 종종 가장 어려운 것이다. 이 절에서 우리는 단방향 매핑들에서 시작하고, 그런 다음 양방향 경우들을
+ 검토함으로써, 하나씩 표준적인 경우들을 상세히 논의할 것이다. 우리는 모든 예제들에서 Person과
+ Address를 사용할 것이다.
+
+
+
+ 우리는 연관들을 중재하는 join 테이블로 매핑시킬 것인지 여부에 따라, 그리고 multiplicity(다중성)에 따라 연관들을 분류할 것이다.
+
+
+
+ null 허용 가능한 foreign 키들은 전통적인 데이터 모델링에서 좋은 실례로 간주되지 않아서, 모든 우리의 예제들은 not null
+ foreign 키들을 사용한다. 이것은 Hibernate에서 필수가 아니고, 당신이 null 허용 가능 컨스트레인트들을 드롭시킬 경우 매핑들은
+ 모두 동작할 것이다.
+
+
+
+
+
+ 단방향 연관들
+
+
+ many to one
+
+
+ 단방향 many-to-one 연관은 가장 공통적인 종류의 단방향 연관이다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+
+
+ one to one
+
+
+ foreign 키에 대한 단방향 one-to-one 연관은 대개 아주 동일하다. 유일한 차이점은
+ 컬럼 유일(unique) 컨스트레인트이다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+ 하나의 프라이머리 키에 대한 단방향 one-to-one 연관은 대개 특별한 id 생성기를 사용한다.
+ (이 예제에서 연관의 방향이 역전되었음을 주목하라.)
+
+
+
+
+
+
+
+
+
+
+
+ person
+
+
+
+]]>
+
+
+
+
+
+ one to many
+
+
+ 하나의 foreign 키에 대한 단방향 one-to-many 연관은 매우 색다른 경우이고, 실제로 권장되지 않는다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+ 우리는 이런 종류의 연관에 대해 하나의 join 테이블을 사용하는 것이 더 좋다고 생각한다.
+
+
+
+
+
+
+
+ join 테이블들에 대한 단방향 연관들
+
+
+ one to many
+
+
+ 하나의 join 테이블에 대한 단방향 one-to-many 연관이 보다 더 선호된다. unique="true"를
+ 지정함으로써 우리는 many-to-many에서 one-to-many로 아중성(multiplicity)를 변경시켰음을 주목하라.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+
+
+ many to one
+
+
+ 하나의 join 테이블에 대한 단방향 many-to-one 연관은 그 연관이 선택적일 때 매우 공통적이다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+
+
+ one to one
+
+
+ 하나의 join 테이블에 대한 단방향 one-to-one 연관은 극히 통상적이지 않지만 가능하다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+
+
+ many to many
+
+
+ 마지막으로, 우리는 단방향 many-to-many 연관을 갖는다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+
+
+
+
+ 양방향 연관들
+
+
+ one to many / many to one
+
+
+ 양방향 many-to-one 연관은 가장 공통된 종류의 연관이다.(이것은 표준 부모/자식 관계이다. )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+
+
+
+ one to one
+
+
+ foreign에 대한 양방향 one-to-one 연관은 꽤 공통적이다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+ 하나의 프라이머리 키에 대한 양방향 one-to-one 연관은 특별한 id 생성기를 사용한다.
+
+
+
+
+
+
+
+
+
+
+
+
+ person
+
+
+
+]]>
+
+
+
+
+
+
+
+ join 테이블들에 대한 양방향 연관들
+
+
+ one to many / many to one
+
+
+ 하나의 join 테이블에 대한 양방향 one-to-many 연관. inverse="true"는
+ 연관의 어느 쪽 끝이든 콜렉션 측으로 또는 join 측으로 갈 수 있다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+
+
+ one to one
+
+
+ 하나의 join 테이블에 대한 양방향 one-to-one 연관은 극히 통상적이지 않지만, 가능하다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+
+
+ many to many
+
+
+ 마지막으로, 우리는 하나의 양방향 many-to-many 연관을 갖는다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+
+
+
+
+
+
+
diff --git a/reference/ko/modules/basic_mapping.xml b/reference/ko/modules/basic_mapping.xml
new file mode 100644
index 0000000000..5de799e907
--- /dev/null
+++ b/reference/ko/modules/basic_mapping.xml
@@ -0,0 +1,2962 @@
+
+ 기본 O/R 매핑
+
+
+ 매핑 선언
+
+
+ 객체/관계형 매핑들은 대개 XML 문서 내에 정의된다. 매핑 문서는 가독성이 있고 수작업 편집이 가능하도록
+ 설계되어 있다. 매핑 언어는 매핑들이 테이블 선언들이 아닌, 영속 클래스 선언들로 생성된다는 의미에서
+ 자바 중심적이다.
+
+
+
+ 심지어 많은 Hibernate 사용자들이 수작업으로 XML을 작성하고자 선택할지라도, XDoclet, Middlegen,
+ 그리고 AndroMDA를 포함하는, 매핑 문서를 생성시키는 많은 도구들이 존재한다는 점을 노트하라.
+
+
+
+ 예제 매핑으로 시작하자:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ 우리는 이제 매핑 문서의 내용을 논의할 것이다. 우리는 Hibernate에 의해 실행 시에 사용되는 문서 요소들과
+ 속성들 만을 설명할 것이다. 매핑 문서는 또한 스키마 내보내기 도구에 의해 내보내진 데이터베이스 스키마에
+ 영향을 주는 어떤 특별한 옵션 속성들과 요소들을 포함한다. (예를 들어 not-null 속성.)
+
+
+
+
+
+ Doctype
+
+
+ 모든 XML 매핑들은 doctype이 보이게 선언해야 한다. 실제 DTD는 위의 URL에서,
+ hibernate-x.x.x/src/org/hibernate 디렉토리 내에서 또는 hibernate3.jar
+ 내에서 찾을 수 있다. Hibernate는 항상 첫 번째로 그것의 classpath 속에서 DTD를 찾게 될 것이다. 만일
+ 당신이 인터넷 연결을 사용하는 DTD에 대한 룩업들을 겪게 될 경우, 당신의 classpath의 컨텐츠에 대해 당신의 DTD 선언을
+ 체크하라.
+
+
+
+
+ hibernate-mapping
+
+
+ 이 요소는 몇 개의 선택적인 속성들을 갖는다. schema 속성과 catalog
+ 속성은 이 매핑 내에서 참조된 테이블들이 명명된 schema 와/또는 catalog에 속한다는 점을 지정한다. 만일 지정될 경우,
+ 테이블 이름들은 주어진 schema 이름과 catalog 이름에 의해 한정(수식)될 것이다. 누락될 경우, 테이블 이름들은
+ 한정되지((수식어가 붙지) 않을 것이다. default-cascade 속성은 cascade
+ 속성을 지정하지 않은 프로퍼티들과 콜렉션들에 대해 전제될 cascade 스타일이 무엇인지를 지정한다.
+ auto-import 속성은 디폴트로 우리가 질의 언어 속에서 수식어가 붙지 않은(unqualified)
+ 클래스 이름들을 사용하게 할 것이다.
+
+
+
+
+
+
+
+
+
+
+
+
+ ]]>
+
+
+
+ schema (옵션): 데이터베이스 스키마의 이름.
+
+
+
+
+ catalog (옵션): 데이터베이스 카다록의 이름.
+
+
+
+
+ default-cascade (옵션 - 디폴트는 none):
+ 디폴트 cascade 스타일.
+
+
+
+
+ default-access (옵션 - 디폴트는 property):
+ Hibernate가 모든 프로퍼티들에 액세스하는데 사용하게 될 방도. PropertyAccessor에
+ 대한 맞춤형 구현일 수 있다.
+
+
+
+
+ default-lazy (옵션 - 디폴트는 true):
+ class 및 collection 매핑들의 지정되지 않은 lazy 속성들에 대한 디폴트 값.
+
+
+
+
+ auto-import (옵션 - 디폴트는 true):
+ 우리가 질의 언어 내에 (이 매핑에서 클래스들에 대해) 수식어가 붙지 않은 클래스 이름들을 사용할 수 있는지를
+ 지정한다.
+
+
+
+
+ package (옵션): 매핑 문서 내에서 수식어가 붙지 않은 클래스 이름들에 대해
+ 가정할 패키지 접두어를 지정한다.
+
+
+
+
+
+
+ 만일 당신이 동일한 (수식어가 붙지 않은) 이름을 가진 두 개의 영속 클래스들을 갖고 있다면, 당신은 auto-import="false"를
+ 설정해야 한다. 만일 당신이 두 개의 클래스들에 동일한 "imported" 이름을 할당하려고 시도할 경우에 Hibernate는 예외상황을 던질 것이다.
+
+
+
+ 위에 보여진 것처럼 hibernate-mapping 요소는 몇몇 영속 <class> 매핑들을 내부에 포함하는
+ 것을 허용해준다는 점을 노트하라. 하지만 한 개의 매핑 파일 속에 한 개의 영속 클래스(또는 한 개의 클래스 계층구조) 만을 매핑하고 영속 서브 클래스 뒤에
+ 그것을 명명하는 것이 좋은 연습이다 (그리고 몇몇 도구들에 의해 기대된다). 예를 들면 Cat.hbm.xml,
+ Dog.hbm.xml 또는 상속을 사용할 경우에는 Animal.hbm.xml.
+
+
+
+
+
+ class
+
+
+ 당신은 class 요소를 사용하여 영속 클래스를 선언할 수도 있다:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ]]>
+
+
+
+ name (옵션): 영속 클래스(또는 인터페이스)의 전체 수식어가 붙은 Java 클래스 이름.
+ 만일 이 속성이 누락될 경우, 매핑이 non-POJO 엔티티라고 가정된다.
+
+
+
+
+ table (옵션 - 디폴트는 수식어가 붙지 않은 클래스명): 그것의 데이터베이스 테이블의 이름.
+
+
+
+
+ discriminator-value (옵션 - 디폴트는 클래스 이름): 다형성(polymorphic) 특징에 사용되는,
+ 개별 서브 클래스들를 구별짓는 값. 허용가능한 값들은null과 not null을 포함한다.
+
+
+
+
+ mutable (옵션 - 디폴트는 true): 클래스들의 인스턴스들이 가변적인지를
+ (가변적이지 않은지를) 지정한다.
+
+
+
+
+ schema (옵션): 루트 <hibernate-mapping> 요소에 의해 지정된
+ 스키마 이름을 오버라이드 시킨다.
+
+
+
+
+ catalog (옵션): 루트 <hibernate-mapping> 요소에 의해 지정된
+ 카다록 이름을 오버라이드 시킨다.
+
+
+
+
+ proxy (옵션): lazy initializing proxy들에 사용할 인터페이스를 지정한다. 당신은 클래스
+ 그 자체의 이름을 지정할 수 도 있다.
+
+
+
+
+ dynamic-update (옵션 - 디폴트는 false):
+ UPDATE SQL이 실행 시에 생성되고 그들 컬럼들의 값들이 변경된 그들 컬럼들 만을
+ 포함할 것인지를 지정한다.
+
+
+
+
+ dynamic-insert (옵션 - 디폴트는 false):
+ 생성될 INSERT이 실행 시에 생성되고 그들 컬럼들의 값이 null이 아닌 컬럼들 만을
+ 포함할 것인지를 지정한다.
+
+
+
+
+ select-before-update (옵션 - 디폴트는 false):
+ 객체가 실제로 변경되는 것이 확실하지 않는 한, Hibernate가 SQL UPDATE를
+ 결코 실행하지 않을 것임을 지정한다. 어떤 경우들에서(실제로 transient
+ 객체가 update()를 사용하여 새로운 session에 연관되었을 때에만), 이것은
+ 하나의 UPDATE가 실제로 필요한 경우인지 여부를 결정하기 위해 Hibernate는
+ 특별한 SQL SELECT를 실행할 것임을 의미한다.
+
+
+
+
+ polymorphism (옵션 - 디폴트는 implicit):
+ implicit 질의 다형성이나 explicit 질의 다형성 중 어느 것이 사용될 것인지를 결정한다.
+
+
+
+
+ where (옵션) 이 클래스의 객체들을 검색할 때 사용될 임의적인 SQL
+ WHERE 조건을 지정한다
+
+
+
+
+ persister (옵션): 맞춤형 ClassPersister를 지정한다.
+
+
+
+
+ batch-size (옵션 - 디폴트는 1) 식별자에 의해 이 클래스의
+ 인스턴스들을 페치시키는 "배치 사이즈"를 지정한다.
+
+
+
+
+ optimistic-lock (옵션 - 디폴트는 version):
+ optimistic 잠금 방도를 결정한다.
+
+
+
+
+ lazy (옵션): lazy="false"를 설정함으로써
+ Lazy fetching이 전체적으로 사용불가능하게 될 수 있다.
+
+
+
+
+ entity-name(옵션, 디폴트는 클래스 이름): Hibernate3는 하나의 클래스가
+ (잠정적으로 다른 테이블들로) 여러번 매핑되는 것을 허용해주고, Java 레벨에서 Map 또는 XML에 의해 표현
+ 되는 엔티티 매핑들을 허용한다. 이들 경우들에서, 당신은 그 엔티티에 대한 명시적인 임의의 이름을 제공해야 한다.
+ entity-name (옵션): Hibernate3는 하나의 클래스가 (잠정적으로 다른 테이블들로)
+ 여러 번 매핑되는 것을 허용하며, 자바 레벨에서 Map들 또는 XML에 의해 표현되는 엔티티 매핑들을 허용한다.
+ 이들 경우들에서, 당신은 그 엔티티들에 대한 명시적인 임의의 이름을 제공해야 한다. 추가 정보는
+ 과 을 보라.
+
+
+
+
+ check (옵션): 자동적인 스키마 생성을 위한 다중-행 check
+ constraint를 생성시키는데 사용되는 SQL 표현식.
+
+
+
+
+ rowid (옵션): Hibernate는 지원되는 데이터베이스들, 예를 들어 Oracle 상에서 이른바
+ ROWID들을 사용할 수 있고, Hibernate는 당신이 이 옵션을 rowid로 설정하는 경우에 빠른
+ 업데이트를 위한 특별한 rowid 컬럼을 사용할 수 있다. ROWID는 구현 상세이고 저장된
+ 튜플(tuple)의 물리적이니 위치를 표현한다.
+
+
+
+
+ subselect (옵션): 불변의 읽기 전용 엔티티를 데이터베이스 subselect로 매핑시킨다.
+ 당신이 기본 테이블 대신에 뷰를 갖고자 원할 경우에 유용하지만, 사용을 자제하라. 추가 정보는 아래를 보라.
+
+
+
+
+ abstract (옵션): <union-subclass> 계층 구조들 내에서
+ abstract 슈퍼클래스들을 마크하는데 사용된다.
+
+
+
+
+
+
+ 명명된 영속 클래스가 인터페이스가 되는 것은 완전히 수용가능하다. 그런 다음 당신은 <subclass>
+ 요소를 사용하여 그 인터페이스에 대한 구현 클래스들을 선언할 것이다. 당신은 임의의 static inner
+ 클래스를 영속화 시킬 수 있다. 당신은 표준 형식, 예를 들어 eg.Foo$Bar를 사용하여 클래스 이름을
+ 지정해야 한다.
+
+
+
+ 불변의 클래스, mutable="false"는 어플리케이션에 의해 업데이트되지 않을 것이거나 삭제되지 않을 것이다.
+ 이것은 Hibernate로 하여금 어떤 마이너 퍼포먼스 최적화를 행하게끔 허용해준다.
+
+
+
+ 선택적인 proxy 속성은 그 클래스의 영속 인스턴스들에 대한 lazy 초기화를 가능하게 해준다. Hibernate는
+ 명명된 인터페이스를 구현하는 CGLIB 프락시들을 초기에 반환할 것이다. 실제 영속 객체는 프락시의 메소드가 호출될 때 로드될 것이다.
+ 아래 "Lazy 초기화를 위한 프락시들"을 보라.
+
+
+ Implicit 다형성은 클래스의 인스턴스들이 어떤 서브클래스나 구현된 인터페이스 또는 클래스를 명명하는
+ 질의에 의해 반환될 것임을 의미하고 그 클래스의 어떤 서브클래스에 대한 인스턴스들이 그 클래스 자체를 명명하는 질의에 의해 반환될 것임을
+ 의미한다. Explicit 다형성은 클래스 인스턴스들이 그 클래스를 명시적으로 명명하는 질의들에 의해서만
+ 반환될 것임을 의미고 그 클래스를 명명하는 질의들이 이 <class> 선언 내부에서 <subclass>
+ 또는 <joined-subclass>로 매핑된 서브 클래스들의 인스턴스들 만을 반환하게 될 것임을 의미한다.
+ 대부분의 용도로, 디폴트인 polymorphism="implicit"가 적절하다.두 개의 다른 클래스들이 동일한 테이블로
+ 매핑될 때 Explicit 다형성이 유용하다(이것은 테이블 컬럼들의 서브셋을 포함하는 "경량급" 클래스를 허용한다).
+
+
+
+ persister 속성은 클래스에 사용되는 영속화 방도를 당신이 커스트마이징 할 수 있도록 해준다. 예를 들어
+ 당신은 org.hibernate.persister.EntityPersister에 대한 당신 자신의 서브클래스를 지정할 수도
+ 있거나 당신은 심지어 예를 들어 플랫 파일들이나 LDAP로의 직렬화,내장 프로시저 호출들을 통해 영속화를 구현하는 인터페이스
+ org.hibernate.persister.ClassPersister에 대한 완전히 새로운 구현을 제공할 수도 있다.
+ (Hashtable로의 "영속성"에 관한) 간단한 예제는
+ org.hibernate.test.CustomPersister를 보라.
+
+
+
+ dynamic-update 설정과 dynamic-insert 설정은 서브클래스들에 의해
+ 상속되지 않고 따라서 또한 <subclass> 또는 <joined-subclass>
+ 요소들 상에 지정될 수도 있음을 노트하라. 이들 설정들은 몇몇 경우들에서 퍼포먼스를 증가시키지만 다른 경우들에서는 퍼포먼스를
+ 실제로 감소시킬 수도 있다. 적절하게 사용하라.
+
+
+
+ select-before-update 사용은 대개 퍼포먼스를 감소시킬 것이다. 당신이 detached 인스턴스들의
+ 그래프를 Session에 다시 첨부할 경우에 그것은 데이터베이스 업데이트 트리거가 불필요하게 호출되는
+ 것을 방지하는데 매우 유용하다.
+
+
+
+ dynamic-update를 사용가능하게 할 경우, 당신은 다음 optimistic 잠금 전략들을 선택하게 될 것이다:
+
+
+
+
+ version은 version/timestamp 컬럼들을 체크한다
+
+
+
+
+ all은 모든 컬럼들을 체크한다
+
+
+
+
+ dirty는 몇몇 동시성 업데이트들을 허용하여, 변경된 컬럼들을 체크한다
+
+
+
+
+ none은 optimistic 잠금을 사용하지 않는다
+
+
+
+
+ 우리는 당신이 Hibernate에서 optimistic 잠금을 위해 version/timestamp 컬럼들을 사용할 것을 매우 강력하게
+ 권장한다. 이것은 퍼포먼스에 대해 최적의 방도이고 detached 인스턴스들에 대해 행해진 변경들을 정확하게 핸들링하는 유일한 방도이다(예를 들어
+ Session.merge()가 사용될 때).
+
+
+
+ Hibernate 매핑의 경우에 베이스 테이블과 뷰 사이에 차이점이 존재하지 않는다. 왜냐하면 이것이 데이터베이스 레벨에서는 투명하다고 기대되기
+ 때문이다(몇몇 DBMS는 뷰를 고유하게 지원하지 않고 특히 뷰 업데이트를 지원하지 않음을 노트하라). 때때로 당신이 뷰를 사용하고자 원하지만,
+ (예를 들어 리거시 스키마로) 데이터베이스 속에 뷰를 생성시킬 수 없다. 이 경우에, 당신은 불변의 읽기 전용 엔티티를 주어진 SQL subselect
+ 표현식으로 매핑시킬 수 있다:
+
+
+
+
+ select item.name, max(bid.amount), count(*)
+ from item
+ join bid on bid.item_id = item.id
+ group by item.name
+
+
+
+
+ ...
+]]>
+
+
+ auto-flush가 정확하게 발생하도록 하고, 그리고 파생된 엔티티에 대한 질의들이 쓸효성 없는 데이터를 반환하지 않도록 함으로써, 이 엔티티와 동기화 될
+ 테이블을 선언하라. <subselect>는 속성과 내포된 매핑 요소 양자로서 이용 가능하다.
+
+
+
+
+
+ id
+
+
+ 매핑된 클래스들은 데이터베이스 테이블의 프라이머리 키 컬럼을 선언해야 한다. 대부분의 클래스들은 또한 인스턴스의 유일 식별자를 소유하는
+ 자바빈즈-스타일 프로퍼티를 가질 것이다. <id> 요소는 그 프로퍼티로부터 프라이머리 키 컬럼으로의 매핑을 정의한다.
+
+
+
+
+
+
+
+
+
+
+
+ node="element-name|@attribute-name|element/@attribute|."
+
+
+]]>
+
+
+
+ name (옵션): 식별자 프로퍼티의 이름.
+
+
+
+
+ type (옵션): Hibernate 타입을 나타내는 이름.
+
+
+
+
+ column (옵션 - 디폴트는 프로퍼티 이름): 프라이머리 키 컬럼의 이름.
+
+
+
+
+ unsaved-value (옵션 - 디폴트는 "sensible" 값):
+ 이전 세션에서 저장되었거나 로드되었던 detached(분리된) 인스턴스들로부터 그것을 구분지우도록, 인스턴스가 새로이 초기화되어 있음(저장되어
+ 있지 않음)을 나타내는 식별자 프로퍼티 값.
+
+
+
+
+ access (옵션 - 디폴트는 property):
+ Hibernate가 프로퍼티 값에 액세스하는데 사용할 방도.
+
+
+
+
+
+
+ name 속성이 누락되면, 클래스는 식별자 프로퍼티를 갖지 않는다고 가정된다.
+
+
+
+ unsaved-value 속성은 중요하다! 만일 당신의 클래스의 식별자 프로퍼티가 디폴트로 통상의 Java
+ 디폴트 값(null 또는 0)에 대해 디폴트가 아닐 경우, 당신은 실제 디폴트를 지정해야 할 것이다.
+
+
+
+ composite 키들로서 리거시 데이터에 액세스하는 것을 허용해주는 대체적인 <composite-id>
+ 선언이 존재한다. 우리는 그 밖의 어떤것에 대한 그것의 사용에 대해 강력하게 반대한다.
+
+
+
+ Generator
+
+
+ 선택적인 <generator> 자식 요소는 영속 클래스의 인스턴스들에 대한 유일 식별자들을 생성시키는데 사용되는
+ 자바 클래스를 명명한다. 만일 임의의 파라미터들이 생성기 인스턴스를 구성하거나 초기화 시키는데 필요할 경우, 그것들은 <param>
+ 요소 를 사용하여 전달된다.
+
+
+
+
+ uid_table
+ next_hi_value_column
+
+]]>
+
+
+ 모든 생성기들은 org.hibernate.id.IdentifierGenerator 인터페이스를 구현한다. 이것은 매우 간단한 인터페이스이다;
+ 몇몇 어플리케이션들은 그것들 자신의 특화된 구현들을 제공하도록 선택할 수 있다. 하지만 Hibernate는 미리 빈드된 구현들의 영역들을 제공한다.
+ 빌드-인 생성기(generator)들에 대한 단축 이름들이 존재한다:
+
+
+
+ increment
+
+
+ 동일한 테이블 속으로 데이터를 입력하는 다른 프로세스가 없을 때에만 유일한 long, short 또는 int
+ 타입의 식별자들을 생성시킨다. 클러스터 내에서는 사용하지 말라.
+
+
+
+
+ identity
+
+
+ DB2, MySQL, MS SQL Server, Sybase, HypersonicSQL에서 식별 컬럼들을 지원한다. 반환되는 식별자는 long,
+ short 또는 int 타입이다.
+
+
+
+
+ sequence
+
+
+ DB2, PostgreSQL, Oracle, SAP DB, McKoi에서 시퀀스를 사용하거나 Interbase에서 생성기(generator)를 사용한다. 반환되는 식별자는
+ long, short 또는 int 타입이다.
+
+
+
+
+ hilo
+
+
+ 테이블과 컬럼(디폴트로 각각 hibernate_unique_key와 next_hi)이 hi 값들의
+ 소스로서 주어지면, long, short 또는 int 타입의
+ 식별자들을 효과적으로 생성시키는데 hi/lo 알고리즘을 사용한다. hi/lo 알고리즘은 특정 데이터베이스에 대해서만 유일한 식별자들을
+ 생성시킨다.
+
+
+
+
+ seqhilo
+
+
+ 명명된 데이터베이스 시퀀스가 주어지면, long, short 또는 int
+ 타입의 식별자들을 효과적으로 생성시키는데 hi/lo 알고리즘을 사용한다.
+
+
+
+
+ uuid
+
+
+ 네트웍 내에서 유일한(IP 주소가 사용된다) string 타입의 식별자들을 생성시키기 위해 128 비트 UUID 알고리즘을 사용한다.
+ UUID는 길이가 32인 16진수들의 문자열로서 인코딩 된다.
+
+
+
+
+ guid
+
+
+ MS SQL Server와 MySQL 상에서 데이터베이스 생성 GUID 문자열을 사용한다.
+
+
+
+
+ native
+
+
+ 기본 데이터베이스의 가용성들에 의존하여 identity, sequence
+ 또는 hilo를 찾아낸다.
+
+
+
+
+ assigned
+
+
+ 어플리케이션으로 하여금 save()가 호출되기 전에 식별자를 객체에 할당하도록 한다.
+ <generator> 요소가 지정되지 않을 경우 이것이 디폴트 방도이다.
+
+
+
+
+ select
+
+
+ 어떤 유일 키에 의해 행을 select하고 프라이머리 키 값을 검색함으로써 데이터베이스 트리거에 의해 할당된
+ 프라이머리 키를 검색한다.
+
+
+
+
+ foreign
+
+
+ 또 다른 연관된 객체의 식별자를 사용한다. 대개 <one-to-one> 프라이머리 키
+ 연관관계와 함께 사용된다.
+
+
+
+
+
+
+
+
+
+ Hi/lo algorithm
+
+ hilo와 seqhilo 생성기들은 식별자 생성에 대한 마음에 드는 접근법인,
+ hi/lo 알고리즘에 대한 두 개의 대체 구현들은 제공한다. 첫 번째 구현은 다음에 이용 가능한 "hi" 값을 수용하기 위한 "특별한"
+ 데이터베이스 테이블을 필요로 한다. 두 번째는 (지원되는) Oracle 스타일의 시퀀스를 사용한다.
+
+
+
+
+ hi_value
+ next_value
+ 100
+
+]]>
+
+
+
+ hi_value
+ 100
+
+]]>
+
+
+ 불행히도 당신은 Hibernate에 당신 자신의 Connection을 제공할 때 hilo를
+ 사용할 수 없다. Hibernate가 JTA의 도움을 받는 커넥션들을 얻기 위해 어플리케이션 서버 데이터소스를 사용할 때 당신은
+ hibernate.transaction.manager_lookup_class를 적절하게 구성해야 한다.
+
+
+
+
+ UUID 알고리즘
+
+ UUID 는 다음을 포함한다: IP 주소, JVM의 시작 시간(정확히 1/4 초), 시스템 시간과 (JVM 내에서 유일한) counter 값.
+ Java 코드로부터 MAC 주소 또는 메모리 주소를 얻는 것은 불가능하여서, 이것은 우리가 JNI를 사용하지 않고서 행할 수 있는
+ 최상의 것이다.
+
+
+
+
+ 식별 컬럼들과 시퀀스들
+
+ 식별 컬럼들을 지원하는 데이터베이스들(DB2, MySQL, Sybase, MS SQL)의 경우, 당신은 identity 키
+ 생성을 사용할 수 있다. 시퀀스들을 지원하는 데이터베이스들(DB2, Oracle, PostgreSQL, Interbase, McKoi, SAP DB)의
+ 경우, 당신은 sequence 스타일 키 생성을 사용할 수도 있다. 이들 방도들 모두 새로운 객체를 insert하기
+ 위해 두 개의 SQL 질의들을 필요로 한다.
+
+
+
+
+ person_id_sequence
+
+]]>
+
+
+
+]]>
+
+
+ 크로스 플랫폼 개발을 위해서, native 방도가 기준 데이터베이스들의 가용성들에 따라 identity,
+ sequence, hilo 방도 중에서 선택될 것이다.
+
+
+
+
+ 할당된 식별자들
+
+ (Hibernate로 하여금 식별자들을 생성시키도록 하는 것과는 반대로) 당신이 어플리케이션으로 하여금 식별자들을 할당하도록 원할 경우,
+ 당신은 assigned 생성기를 사용할 수 있다. 이 특별한 생성기는 객체의 identifier 프로퍼티에 이미 할당된
+ 식별자 값을 사용할 것이다. 이 생성기(generator)는 프라이머리 키가 대용(surrogate ) 키 대신에 natural 키일 때 사용된다.
+ 당신이 <generator> 요소를 지정하지 않을 경우에 이것이 디폴트 특징이다
+
+
+
+ assigned 생성기(generator)를 선택하는 것은 , version 또는 timestamp 프로퍼티가 존재하지 않는 한
+ 또는 당신이 Interceptor.isUnsaved()를 정의하지 않는 한, 하나의 인스턴스가 transient 또는 detached인지를
+ 결정하기 위해 Hibernae로 하여금 데이터베이스에 접촉하도록 강제하는, unsaved-value="undefined"를
+ Hibernate에게 사용하도록 한다.
+
+
+
+
+ 트리거들에 의해 할당된 프라이머리 키들
+
+ 리거시 스키마에 대해서만(Hibernate는 트리거들을 가진 DDL을 생성시키지 않는다).
+
+
+
+
+ socialSecurityNumber
+
+]]>
+
+
+ 위의 예제에서, natural 키로서 클래스에 의해 socialSecurityNumber로 명명된 유일 값을 가진 프로퍼티가 존재하고,
+ 트리거에 의해 그 값이 생성되는 person_id로 명명된 대용키가 존재한다.
+
+
+
+
+
+
+
+ composite-id
+
+
+ node="element-name|."
+
+
+
+ ......
+]]>
+
+
+ composite 키를 가진 테이블의 경우, 당신은 클래스의 여러 프로퍼티들을 식별자 프로퍼티들로서 매핑할 수 있다.
+ <composite-id> 요소는 자식 요소들로서 <key-property>
+ 프로퍼티 매핑과 <key-many-to-one> 매핑들을 허용한다.
+
+
+
+
+
+]]>
+
+
+ 당신의 영속 클래스는 composite 식별자 동등성을 구현하기 위해서 equals()와
+ hashCode()를 오버라이드 시켜야 한다. 그것은 또한
+ Serializable을 구현해야 한다.
+
+
+
+ 불행히도, composite 식별자들에 대한 이 접근법은 영속 객체가 그것 자신의 식별자라는 점을 의미한다. 객체
+ 자신 외의 다른 "핸들"이 존재하지 않는다. 당신은 당신이 composite key에 연관된 영속 상태를 load()
+ 할 수 있기 이전에 영속 클래스 그 자체의 인스턴스를 초기화 하고 그것의 식별자 프로퍼티들을 군집화 시켜야 한다. 우리는
+ 에서 composite 식별자가 한 개의 별도의 클래스로서 구현되는 훨씬
+ 더 편리한 접근법을 설명할 것이다. 아래에 설명된 속성들은 이 대체 접근법에만 적용된다:
+
+
+
+
+
+ name (옵션): composite 식별자를 갖고 있는 컴포넌트 타입의 프로퍼티(다음 절을 보라).
+
+
+
+
+ class (옵션 - 디폴트는 reflection에 의해 결정된 프로퍼티 타입):
+ composite 식별자로서 사용된 컴포넌트 클래스(다음 절을 보라).
+
+
+
+
+ unsaved-value (옵션 - 디폴트는 undefined):
+ any로 설정될 경우에 transient 인스턴스들이 새로이 초기화 된 것으로 간주되고
+ 또는none으로 설정된 경우, transient 인스턴스들이 detached 된 것으로 간주될 것임을 나타낸다.
+ 모든 클래스에서 디폴트 값으로 남겨두는 것이 최상이다.
+
+
+
+
+
+
+
+ discriminator
+
+
+ <discriminator> 요소는 table-per-class-hierarchy(테이블 당 클래스 계층구조)
+ 매핑 방도를 사용하는 다형성 영속화에 필요하고 테이블의 discriminator(판별자) 컬럼을 선언한다. discriminator 컬럼은
+ 특정 행에 대해 초기화 시킬 서브 클래스가 무엇인지를 영속 계층에 알려주는 표시자 값들을 포함한다. 타입들의 제한적인 집합이
+ 사용될 수 있다: string, character, integer,
+ byte, short, boolean,
+ yes_no, true_false.
+
+
+
+
+
+
+
+
+
+
+ ]]>
+
+
+
+ column (옵션 - 디폴트는 class)
+ discriminator 컬럼명.
+
+
+
+
+ type (옵션 - 디폴트는 string)
+ Hibernate 타입을 나타내는 이름
+
+
+
+
+ force (옵션 - 디폴트는 false)
+ 이것은 Hibernate로 하여금 루트 클래스의 모든 인스턴스들을 검색할 때조차도 허용된 discriminator
+ 값들을 지정하도록 "강제한다".
+
+
+
+
+ insert (옵션 - 디폴트는 true)
+ 당신의 discriminator 컬럼이 또한 매핑된 composite 식별자의 부분일 경우에 이것을 false로 설정하라.
+ (Hibernate에게 SQL INSERT들 속에 그 컬럼을 포함하지 않도록 통보한다.)
+
+
+
+
+ formula (옵션)
+ 타입이 평가 되어야 할 때 실행되는 임의의 SQL 표현식. 컨텐츠 기반의 판별을 허용해준다.
+
+
+
+
+
+
+ discriminator 컬럼의 실제 값들은 <class> 요소와
+ <subclass> 요소의 discriminator-value 속성에 의해 지정된다.
+
+
+
+ force 속성은 테이블이 영속 클래스로 매핑되지 않는 "특별한" discriminator 값들을 가진 행들을
+ 포함할 경우에(만) 유용하다. 이것은 대개 그 경우가 아닐 것이다.
+
+
+
+ formula 속성을 사용하여 당신은 행의 타입을 판단하는데 사용될 임의의 SQL 표현식을 선언할 수 있다:
+
+
+ ]]>
+
+
+
+
+ version (옵션)
+
+
+ <version> 요소는 옵션이고 테이블이 버전화된 데이터를 포함한다는 것을 나타낸다.
+ 이것은 당신이 긴 트랜잭션(long transaction)들을 사용할 계획이라면 특히 유용하다
+ (아래를 보라).
+
+
+
+
+
+
+
+
+
+
+ ]]>
+
+
+
+ column (옵션 - 디폴트는 프로퍼티 명):
+ 버전 번호를 가진 컬럼의 이름.
+
+
+
+
+ name: 영속 클래스의 프로퍼티 명.
+
+
+
+
+ type (옵션 - 디폴트는 integer):
+ 버전 번호의 타입.
+
+
+
+
+ access (옵션 - 디폴트는 property):
+ Hibernate가 프로퍼티 값에 액세스하는데 사용할 방도.
+
+
+
+
+ unsaved-value (옵션 - 디폴트는 undefined):
+ 이전 세션에서 저장되었거나 로드되었던 detached 인스턴스로부터 구별지어서, 인스턴스가 새로이 초기화됨(unsaved)을
+ 나타내는 version 프로퍼티 값.(undefined는 식별자 프로퍼티 값이 사용될 것임을 지정한다.)
+
+
+
+
+
+
+ 버전 번호들은 long, integer, short,
+ timestamp 또는 calendar 타입일 수 있다.
+
+
+
+ version 또는 timestamp 프로퍼티는 detached 인스턴스에 대해 결코 null일 수가 없어서, Hibernate는
+ 다른 unsaved-value 방도들이 지정되는 것에 상관없이, null version이나 timestamp를
+ 가진 임의의 인스턴스를 transient로서 검출할 것이다. null 허용되는 version 이나 property를
+ 선언하는 것은 Hibernate에서 transitive reattachment에 대한 임의의 문제들을 피하는 쉬운 방법이고,
+ assigned 식별자들이나 composite key들을 사용하는 사람들에게 특히 유용하다!
+
+
+
+
+ timestamp (옵션)
+
+
+ 옵션 <timestamp> 요소는 테이블이 타임스탬프화 된 데이터를 포함함을 나타낸다. 이것은
+ 버전화에 대한 대체물로서 고안되었다. Timestamp은 고유하게 optimistic 잠금에 대한 다소 안전한 구현이다. 하지만 때때로
+ 어플리케이션은 다른 방법들로 timestamp들을 사용할 수도 있다.
+
+
+
+
+
+
+
+
+
+ ]]>
+
+
+
+ column (옵션 - 디폴트는 프로퍼티 명):
+ 타임스탬프를 포함하는 컬럼 명.
+
+
+
+
+ name:
+ 영속 클래스에 대해 자바 Date 또는 Timestamp 타입을
+ 가진 자바빈즈 스타일의 프로퍼티 이름.
+
+
+
+
+ access (옵션 - 디폴트는 property):
+ Hibernate가 프로퍼티 값에 접근하는데 사용할 방도.
+
+
+
+
+ unsaved-value (옵션 - 디폴트는 null):
+ 이전 세션에서 저장되었거나 로드되었던 detached 인스턴스로부터 인스턴스를 구별지우는, 인스턴스가 새로이
+ 초기화됨(unsaved)을 나타내는 version 프로퍼티 값.(undefined는 식별자
+ 프로퍼티 값이 사용될 것임을 지정한다.)
+
+
+
+
+
+
+ <timestamp>는 <version type="timestamp">과
+ 같음을 노트하라.
+
+
+
+
+
+ 프로퍼티
+
+
+ <property> 요소는 클래스의 자바빈즈 스타일의 영속 프로퍼티를 선언한다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ]]>
+
+
+
+ name: 첫 소문자로 시작하는 프로퍼티 이름.
+
+
+
+
+ column (옵션 - 디폴트는 프로퍼티 이름):
+ 매핑된 데이터베이스 테이블 컬럼의 이름. 이것은 또한 내부에 포함되는 <column> 요소(들)에
+ 의해 지정될 수도 있다.
+
+
+
+
+ type (옵션): Hibernate 타입을 나타내는 이름.
+
+
+
+
+ update, insert (옵션 - 디폴트는 true) :
+ 매핑된 컬럼들이 UPDATE와/또는 INSERT 문장들속에 포함될 것임을 지정한다.
+ 둘다 false로 설정하는 것은 그 값이 동일한 컬럼(들)로 매핑되는 어떤 다른 프로퍼티로부터 또는 트리거에
+ 의해 또는 다른 어플리케이션으로부터 초기화 되는 순수하게 "파생된(derived)" 프로퍼티를 허용해준다.
+
+
+
+
+ formula (옵션):
+ 계산되는 프로퍼티에 대해 값을 정의하는 SQL 표현식. 계산되는 프로퍼티들은
+ 그것들 자신에 대한 컬럼 매핑을 갖지 않는다.
+
+
+
+
+ access (옵션 - 디폴트는 property):
+ Hibernate가 프로퍼티 값에 접근하는데 사용할 방도.
+
+
+
+
+ lazy (옵션 - 디폴트는 false):
+ 인스턴스 변수가 처음으로 액세스 될 때 이 프로퍼티가 lazily하게 페치될 것임을 지정한다(빌드-시 바이트코드
+ 수단을 필요로 한다).
+
+
+
+
+ unique (옵션):
+ 컬럼들에 대한 유일 컨스트레인트의 DDL 생성을 가능하게 만든다. 또한 이것이 property-ref의
+ 타켓이 되는 것을 허용해준다.
+
+
+
+
+ not-null (옵션):
+ 컬럼들에 대해 null 가능 컨스트레인트의 DDL 생성을 가능하게 만든다.
+
+
+
+
+ optimistic-lock (옵션 - 디폴트는 true):
+ 이 프로퍼티에 대한 업데이트들이 optimistic 잠금을 획득하는 것을 필요로 하거나 필요로 하지 않음을 지정한다.
+ 달리말해, 이 프로퍼티가 dirty일 때 버전 증가가 발생할 경우인지를 결정한다.
+
+
+
+
+
+
+ typename은 다음일 수 있다:
+
+
+
+
+
+ Hibernate 기본 타입의 이름 (예를 들어. integer, string, character, date, timestamp,
+ float, binary, serializable, object, blob).
+
+
+
+
+ 디폴트 기본 타입을 가진 Java 클래스의 이름(예를 들어. int, float,
+ char, java.lang.String, java.util.Date, java.lang.Integer, java.sql.Clob).
+
+
+
+
+ serializable Java 클래스의 이름.
+
+
+
+
+ 맞춤 타입의 클래스 이름(예를 들어. com.illflow.type.MyCustomType).
+
+
+
+
+
+ 만일 당신이 타입을 지정하지 않을 경우, Hibernate는 정확한 Hibernate 타입을 추정하기 위해 명명된 프로퍼티에 대해
+ reflection을 사용할 것이다. Hibernate는 그 순서에서 2,3,4 규칙들을 사용하여 프로퍼티 getter의 반환 클래스의
+ 이름을 해석하려고 시도할 것이다. 하지만 이것은 항상 충분하지는 않다. 어떤 경우들에서, 당신은 여전히 type
+ 속성을 필요로 할 것이다.(예를 들어, Hibernate.DATE와 Hibernate.TIMESTAMP
+ 사이를 구별하기 위해, 또는 맞춤 타입을 지정하기 위해.)
+
+
+
+ access 속성은 당신으로 하여금 Hibernate가 런타임 시에 프로퍼티에 액세스하는 방법을 제어하도록 해준다.
+ 디폴트로 Hibernate는 프로퍼티 get/set 쌍을 호출할 것이다. 만일 당신이 access="field"를 지정할
+ 경우, Hibernate는 get/set 쌍을 피하고 reflection을 사용하여 직접 필드에 액세스 할 것이다. 당신은
+ org.hibernate.property.PropertyAccessor 인터페이스를 구현하는 클래스를 명명함으로써
+ 프로퍼티 접근을 위한 당신 자신의 방도를 지정할 수도 있다.
+
+
+
+ 특별히 강력한 특징은 파생된 플로퍼티들이다. 이들 프로퍼티들은 정의상 읽기 전용이고, 그 프로퍼티 값은 로드 시에 계산된다. 당신은
+ 그 계산을 SQL 표현식으로 선언하고, 이것은 인스턴스를 로드시키는 SQL 질의 내의 SELECT 절 서브질의로
+ 번역된다:
+
+
+ ]]>
+
+
+ 당신은 특정 컬럼(주어진 예제에서는 customerId)에 대해 alias를 선언하지 않음으로써 엔티티들 자신의
+ 테이블을 참조할 수 있음을 노트하라. 또한 당신은 만일 당신이 그 속성을 사용하고 싶지 않을 경우에 내포된 <formula>
+ 매핑 요소를 사용할 수 있음을 노트하라.
+
+
+
+
+
+ many-to-one
+
+
+ 또 다른 영속 클래스에 대한 정규 연관관계는 many-to-one 요소를 사용하여 선언된다. 관계형 모형은
+ many-to-one 연관관계이다.: 하나의 테이블 내에 있는 foreign 키는 대상 테이블의 프라이머리 키 컬럼(들)을 참조하고 있다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ]]>
+
+
+
+ name: 프로퍼티의 이름.
+
+
+
+
+ column (옵션):
+ foreign key 컬럼의 이름. 이것은 또한 내포된 <column> 요소(들)에 의해
+ 지정된다.
+
+
+
+
+ class (옵션 - 디폴트는 reflection에 의해 결정된 프로퍼티 타입):
+ 연관된 클래스의 이름.
+
+
+
+
+ cascade (옵션):
+ 어느 오퍼레이션들이 부모 객체로부터 연관된 객체로 케스케이드 될 것인지를 지정한다.
+
+
+
+
+ fetch (옵션 - 디폴트는 select):
+ outer-join 페칭 또는 sequential select 페칭 사이에서 선택하라.
+
+
+
+
+ update, insert (옵션 - 디폴트는 true)
+ 매핑된 컬럼들이 SQL UPDATE와/또는 INSERT 문장들 속에 포함될 것인지를 지정한다.
+ 둘다 false로 설정하는 것은 그 값이 동일한 컬럼(들)로 매핑시키는 어떤 다른 컬럼들로부터 초기화 되거나 트리거나
+ 다른 어플리케이션에 의해 초기화되는 단순한 "파생된" 연관관계 값을 허용한다.
+
+
+
+
+ property-ref: (옵션) 이 foreign key에 조인되는 연관된 클래스의 프로퍼티 이름. 지정되지 않을 경우,
+ 연관 클래스의 프라이머리 키가 사용된다.
+
+
+
+
+ access (옵션 - 디폴트는 property):
+ Hibernate가 프로퍼티 값에 접근하는데 사용할 방도.
+
+
+
+
+ unique (옵션):
+ foreign-key 컬럼을 위한 유일 컨스트레인트의 DDL 생성을 가능하도록 해준다. 또한 이것이 property-ref의 대상이 되는 것을 허용해준다.
+ 이것은 연관 다중성(association multiplicity)을 효율적으로 일 대 일로 만든다.
+
+
+
+
+ not-null (옵션):
+ foreign key 컬럼들을 위한 null 가능한 컨스트레인트의 DDL 생성을 가능하도록 해준다.
+
+
+
+
+ optimistic-lock (옵션 - 디폴트는 true):
+ 이 프로퍼티에 대한 업데이트들이 optimistic lock의 획득을 필요로 하는지 아닌지 여부를 지정한다.
+ 달리 말해 이 프로퍼티가 dirty일 때 version 증가가 발생해야 할 경우인지를 결정한다.
+
+
+
+
+ lazy (옵션 - 디폴트는 proxy):
+ 디폴트로, 단일 포인트 연관들이 프락시된다. lazy="true"는 인스턴스 변수가 처음으로 접근될 때
+ 그 프로퍼티가 lazily 페치될 것임을 지정한다(빌드-시 바이트코드 수단을 필요로 한다). lazy="false"는
+ 그 연관이 항상 eagerly 페치될 것임을 지정한다.
+
+
+
+
+ not-found (옵션 - 디폴트는 exception):
+ 누락된 행들을 참조하는 foreign key들이 어떻게 처리될 것인지를 지정한다: ignore는 한 개의 누락된 행을
+ 한 개의 null 연관으로 취급할 것이다.
+
+
+
+
+ entity-name (옵션): 연관된 클래스의 엔티티 이름.
+
+
+
+
+
+ formula (옵션): 계산된 foreign key에 대한 값을 정의하는 SQL 표현식.
+
+
+
+
+
+ cascade 속성 값을 none 아닌 어떤 의미있는 다른 값으로 설정하는 것은
+ 어떤 오퍼레이션들을 연관된 객체에게 보급할 것이다. 유의미한 값들은 Hibernate의 기본 오퍼레이션들의 이름들,
+ 즉 persist, merge, delete, save-update, evict, replicate, lock, refresh
+ 뿐만 아니라 특별한 값들, 즉 delete-orphan과 all 그리고 오퍼레이션 이름들의
+ 쉼표 분리된 조합들, 예를 들면 cascade="persist,merge,evict" 또는
+ cascade="all,delete-orphan"이다. 전체 설명은
+ 를 보라.
+
+
+
+ 일반적인 many-to-one 선언은 다음과 같이 간단하게 보여진다:
+
+
+ ]]>
+
+
+ property-ref 속성은 오직 foreign key가 프라이머리 키가 아닌 연관된 테이블의 유일 키를 참조하는
+ 리거시 데이터를 매핑하는데만 사용된다. 이것은 꼴사나운 관계형 모형이다. 예를 들어, Product
+ 클래스가 프라이머리 키를 아닌, 유일한 시리얼 번호를 갖는다고 가정하자.(unique 속성은
+ SchemaExport 도구로 Hibernate의 DDL 생성을 제어한다.)
+
+
+ ]]>
+
+
+ 그런 다음 OrderItem에 대한 매핑은 다음을 사용할 것이다:
+
+
+ ]]>
+
+
+ 하지만 이것은 확실히 권장되지 않는다.
+
+
+
+ 만일 참조된 유일 키가 연관된 엔티티의 여러 프로퍼티들을 포함할 경우, 당신은 명명된 <properties>
+ 요소 내부에 참조된 프로퍼티들을 매핑할 것이다.
+
+
+
+
+
+ one-to-one
+
+
+ 또 다른 영속 클래스에 대한 one-to-one 연관관계는 one-to-one 요소를 사용하여 선언된다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ]]>
+
+
+
+ name: 프로퍼티의 이름.
+
+
+
+
+ class (옵션 - 디폴트는 reflection에 의해 결정된 프로퍼티 타입):
+ 연관된 클래스의 이름.
+
+
+
+
+ cascade (옵션) 어느 오퍼레이션들이 부모 객체로부터 연관된 객체로
+ 케스케이드 될 것인지를 지정한다.
+
+
+
+
+ constrained (옵션) 매핑된 테이블의 프라이머리 키에 대한 foreign 키
+ 컨스트레인트가 연관된 클래스의 테이블을 참조하는지 여부를 지정한다. 이 옵션은 save()와
+ delete()가 케스케이드 되는 순서에 영향을 주고, 그 연관이 프락시 될 것인지 여부를 결정한다
+ (또한 스키마 내보내기 도구에 의해 사용된다).
+
+
+
+
+ fetch (옵션 - 디폴트는 select):
+ outer-join 페칭 또는 순차적인 select 페칭 중에서 선택하라.
+
+
+
+
+ property-ref: (옵션) 이 클래스의 프라이머리 키에 연결된 연관 클래스의 프로퍼티의 이름.
+ 만일 지정되지 않을 경우, 연관 클래스의 프라이머리 키가 사용된다.
+
+
+
+
+ access (옵션 - 디폴트는 property):
+ Hibernate가 프로퍼티 값에 접근 하는데 사용할 방도.
+
+
+
+
+ formula (옵션):
+ 거의 모든 one to one 연관관계들은 소유하는 엔티티의 프라이머리 키로 매핑된다. 이것이 그 경우가 아닌 드문 경우들에서,
+ 당신은 SQL formula 사용에 결합시킬 몇몇 다른 컬럼, 컬럼들, 또는 표현식을 지정할 수 있다.(예제는
+ org.hibernate.test.onetooneformula를 보라.)
+
+
+
+
+ lazy (옵션 - 디폴트는 proxy):
+ 디폴트로 한쪽 끝 연관들이 프락시 된다. lazy="true"는 인스턴스 변수가 처음 접근될 때
+ 그 프로퍼티가 lazily 페치될 것임을 지정한다(빌드-시 바이트코드 수단을 필요로 한다).
+ lazy="false"는 그 연관들이 항상 eagerly 페치될 것임을 지정한다. 만일
+ constrained="false"인 경우에, 프락싱은 불가능하고 Hibernate는 그 연관을 eager 페치시킬 것이다!
+
+
+
+
+ entity-name (옵션): 연관된 클래스의 엔티티 이름.
+
+
+
+
+
+
+ one-to-one 연관관계에는 두 가지 변종이 존재한다:
+
+
+
+ 프라이머리 키 연관관계들
+
+
+ 유일 foreign 키 연관관계들
+
+
+
+
+ 프라이머리 키 연관들은 특별한 테이블 컬럼을 필요로 하지 않는다; 만일 두 개의 행들이 그 연관에 의해 관계지워지면,
+ 두 개의 테이블 행들은 동일한 프라이머리 키 값을 공유한다. 따라서 만일 두 개의 객체들이 프라이머리 키 연관에 의해
+ 관계지워지도록 당신이 원할 경우, 당신은 그것들에 동일한 식별자 값이 할당되도록 해야 한다!
+
+
+
+ 프라이머리 키 연관에 대해, 다음 매핑들을 Employee와 Person 각각에 추가하라.
+
+
+ ]]>
+ ]]>
+
+
+ 이제 우리는 PERSON 과 EMPLOYEE 테이블들에서 관계지워진 행들의 프라이머리 키들이 동일함을 확실히 해야 한다! 우리는
+ foreign로 명명되는 특별한 Hibernate 식별자 생성 방도를 사용한다:
+
+
+
+
+
+ employee
+
+
+ ...
+
+]]>
+
+
+ 그때 Person의 새로이 저장된 인스턴스는 그 Person의
+ employee 프로퍼티에 대해 참조된 Employee 인스턴스와 동일한
+ 프라이머리 키를 할당받는다.
+
+
+
+ 달리, Employee로부터 Person으로의 유일 컨스트레인트를 가진
+ 하나의 foreign key는 다음과 같이 표현될 수 있다:
+
+
+ ]]>
+
+
+ 그리고 이 연관은 다음을 Person 매핑에 추가함으로써 양방향이 될 수 있다:
+
+
+ ]]>
+
+
+
+
+ natural-id
+
+
+
+
+ ......
+]]>
+
+
+ 비록 우리가 프라이머리 키들로서 대용키들을 사용하는 것을 권장했을지라도, 당신은 여전히 모든 엔티티들에 대한 natural
+ 키들을 식별하고자 원할 것이다. narutal 키는 유일(unique)하고 null이 아닌 프로퍼티 또는 프로퍼티들의 조합이다.
+ 그것이 또한 불변하는 것일 경우가 더 좋다. <natural-id> 요소 내부에 있는 natural 키의
+ 프로퍼티들을 매핑하라. Hibernate는 필수적인 유일 키와 null 허용가능한 컨스트레인트들을 생성시킬 것이고, 당신의
+ 매핑은 보다 자가 설명적이게 될 것이다.
+
+
+
+ 우리는 당신이 엔티티에 대한 narutal 키 프로퍼티들을 비교하는데 equals()와
+ hashCode()를 구현할 것을 강력하게 권장한다.
+
+
+
+ 이 매핑은 natural 프라이머리 키들을 가진 엔티티들을 위한 용도로 고안된 것은 아니다.
+
+
+
+
+
+ mutable (옵션, 디폴트는 false):
+ 디폴트로, narutal 식별자 프로퍼티들은 변경될 수 없는 것(상수)으로 가정된다.
+
+
+
+
+
+
+
+ component, dynamic-component
+
+
+ <component> 요소는 자식 객체의 프로퍼티들을 부모 클래스에 대한 테이블의 컬럼들로 매핑시킨다.
+ 컴포넌트들은 그것들 자신의 프로퍼티들, 컴포넌트들, 또는 콜렉션들을 선언한다. 이래 "컴포넌트들"을 보라.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ........
+]]>
+
+
+
+ name: 프로퍼티의 이름.
+
+
+
+
+ class (옵션 - 디폴트는 reflection에 의해 결정된 프로퍼티 타입):
+ 컴포넌트(자식) 클래스의 이름.
+
+
+
+
+ insert: 매핑된 컬럼들이 SQL INSERT들 속에
+ 나타나야 하는가?
+
+
+
+
+ update: 매핑된 컬럼들이 SQL UPDATE들 속에
+ 나타나야 하는가?
+
+
+
+
+ access (옵션 - 디폴트는 property):
+ Hibernate가 프로퍼티 값에 액세스하는데 사용할 방도.
+
+
+
+
+ lazy (옵션 - 디폴트는 false):
+ 인스턴스 변수가 처음으로 액세스될 때 이 컴포넌트가 lazily(느리게) 페치되어야 하는지 여부를 지정한다
+ (빌드 시 바이트코드 수단을 필요로 한다).
+
+
+
+
+ optimistic-lock (옵션 - 디폴트는 true):
+ 이 컴포넌트에 대한 업데이트들이 optimistic 잠금을 획득하는 것을 필요로 하는지 여부를 지정한다.
+ 달리 말해 이 프로퍼티가 dirty 일 때 버전 증가가 발생할 것인지 여부를 결정한다.
+
+
+
+
+ unique (옵션 - 디폴트는 false):
+ 유일 컨스트레인트가 컴포넌트의 모든 매핑된 컬럼들에 대해 존재하는지 여부를 지정한다.
+
+
+
+
+
+
+ 자식 <property> 태그들은 자식 클래스의 프로퍼티들을 테이블 컬럼들로 매핑시킨다.
+
+
+
+ <component> 요소는 컴포넌트 클래스의 프로퍼티를 포함하는 엔티티에 대한 참조로서 매핑시키는
+ <parent> 서브요소를 허용한다.
+
+
+
+ <dynamic-component> 요소는 컴포넌트로서 매핑될Map을 허용한다.
+ 여기서 프로퍼티 이름들은 map의 키들을 참조한다. 을 보라.
+
+
+
+
+
+ properties
+
+
+ <properties> 요소는 클래스의 프로퍼티들의 명명된, 논리적 그룹핑에 대한 정의를 허용한다.
+ 그 구조에 대한 가장 중요한 사용은 그것이 프로퍼티들의 조합이 property-ref의 대상이 되는 것을
+ 허용해준다는 점이다. 또한 그것은 다중 컬럼 유일 컨스트레인느를 정의하는 편리한 방법이다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ........
+]]>
+
+
+
+ name: 그룹핑의 논리적 이름 - 실제 프로퍼티 이름이 아니다.
+
+
+
+
+ insert: 매핑된 컬럼들이 SQL INSERT들 내에 나타날 것인가?
+
+
+
+
+ update: 매핑된 컬럼들이 SQL UPDATE들 내에 나타날 것인가?
+
+
+
+
+ optimistic-lock (옵션 - 디폴트는 true):
+ 이들 프로퍼티들에 대한 업데이트들이 optimistic 잠금의 획득을 필요로 하는지 여부를 지정한다. 달리 말해
+ 이 프로퍼티가 dirty 일 때 버전 증가가 발생할 것인지 여부를 결정한다.
+
+
+
+
+ unique (옵션 - 디폴트는 false):
+ 유일 컨스트레인트가 컴포넌트의 모든 매핑된 컬럼들에 대해 존재하는지 여부를 지정한다.
+
+
+
+
+
+
+ 예를 들어, 만일 우리가 다음 <properties> 매핑을 가질 경우:
+
+
+
+
+ ...
+
+
+
+
+
+]]>
+
+
+ 그 때 우리는 프라이머리 키가 아닌, Person 테이블의 이 유일 키를 참조하는 어떤 리거시 데이터 연관을
+ 가질 수 있다:
+
+
+
+
+
+
+]]>
+
+
+ 우리는 리거시 데이터를 매핑시키는 컨텍스트 바깥에서 이런 종류의 것을 사용하는 것을 권장하지 않는다.
+
+
+
+
+
+ subclass
+
+
+ 마지막으로, 다형성 영속성은 루트 영속 클래스에 대한 각각의 서브클래스 선언을 필요로 한다.(권장되는)
+ table-per-class-hierarchy(테이블 당 클래스 계층구조) 매핑 방도의 경우, <subclass>
+ 선언이 사용된다.
+
+
+
+
+
+
+
+
+
+
+
+
+ .....
+]]>
+
+
+
+ name: 서브클래스의 전체 수식어가 붙은 클래스 이름.
+
+
+
+
+ discriminator-value (옵션 - 디폴트는 클래스 이름):
+ 개개의 서브클래스들을 구분짓는 값.
+
+
+
+
+ proxy (옵션): lazy 초기화 프락시들을 사용하는데 클래스 또는 인터페이스를 지정한다.
+
+
+
+
+ lazy (옵션 - 디폴트는 true):
+ lazy="false" 설정은 lazy 페칭의 사용을 불가능하게 만든다.
+
+
+
+
+
+
+ 각각의 서브클래스는 그것 자신의 영속 프로퍼티들과 서브클래스들을 선언할 것이다. <version>
+ 프로퍼티와 <id> 프로퍼티는 루트 클래스로부터 상속된다고 가정된다. 계층구조 내에서 각각의
+ 서브클래스는 유일한 discriminator-value를 정의해야 한다. none이 지정될 경우, 전체 수식어가
+ 붙은 자바 클래스 이름이 사용된다.
+
+
+
+ 별도의 매핑 문서들 내에서 바로 hibernate-mapping 밑에 subclass,
+ union-subclass, joined-subclass 매핑들을 정의하는 것이 가능하다.
+ 이것은 단지 새로운 매핑 파일을 추가함으로써 클래스 계층구조를 확장하는 것을 당신에게 허용해준다. 당신은 서브클래스 매핑에서 이전에
+ 매핑된 슈퍼클래스를 명명하여 extends 속성을 지정해야 한다. 노트 : 이전 버전에서 이 특징은 매핑 문서들의
+ 순서를 중요하게 만들었다. Hibernate3에서, extends 키워드를 사용할 때 매핑 파일들의 순서는 관계 없다. 하나의 매핑 파일들 내의
+ 순서는 여전히 서브클래스들 앞에 슈퍼클래스들로서 정의될 필요가 있다.
+
+
+
+
+
+
+]]>
+
+
+ 상속 매핑들에 대한 정보는 을 보라.
+
+
+
+
+
+ joined-subclass
+
+
+ 다른 방법으로 각각의 서브클래스는 그것 자신이 테이블로 매핑될 수 있다(table-per-subclass 매핑 방도). 상속된 상태는
+ 슈퍼클래스의 테이블과 조인함으로써 검색된다. 우리는 <joined-subclass> 요소를 사용한다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ .....
+]]>
+
+
+
+ name: 서브클래스의 전체 수식어가 붙은 클래스 명.
+
+
+
+
+ table: 서브클래스 테이블의 이름.
+
+
+
+
+ proxy (옵션): 프락시들을 lazy 초기화 시키는데 사용할 클래스 또는 인터페이스를 지정한다.
+
+
+
+
+ lazy (옵션 - 디폴트는 true):
+ lazy="false" 설정은 lazy 페칭을 사용불가능하게 만든다
+
+
+
+
+
+
+ 판별자(discriminator) 컬럼은 이 매핑 방도에 필요하지 않다. 하지만 각각의 서브클래스는 <key> 요소를
+ 사용하여 객체 식별자를 보관하는 테이블 컬럼을 선언해야 한다. 이 장의 시작 부분에 있는 매핑은 다음과 같이 다시 작성될 것이다:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ 상속 매핑들에 대한 정보는 을 보라.
+
+
+
+
+
+ union-subclass
+
+
+ 제3의 옵션은 상속 계층구조의 concrete 클래스들 만을 테이블들로 매핑하는 것이다 (table-per-concrete-class 방도). 여기서
+ 각각의 테이블은 상속된 상태를 포함하여 클래스의 모든 영속 상태를 정의한다. Hibernate에서, 그것은 그런 상속 계층구조들을
+ 명시적으로 매핑하는데 필수적이지 않다. 당신은 별도의 <class> 선언을 가진 각각의 클래스를
+ 간단히 매핑시킬 수 있다. 하지만 당신이 다형성 연관관계들(예를 들면 당신의 계층구조의 슈퍼클래스에 대한 연관)을 사용하고자 원할
+ 경우, 당신은 <union-subclass> 매핑을 사용할 필요가 있다.
+
+
+
+
+
+
+
+
+
+
+
+
+ .....
+]]>
+
+
+
+ name: 서브클래스의 전체 수식어가 붙은 클래스 명.
+
+
+
+
+ table: 서브클래스 테이블의 이름.
+
+
+
+
+ proxy (옵션): 프락시들을 lazy 초기화 시키는데 사용할 클래스 또는 인터페이스를 지정한다.
+
+
+
+
+ lazy (옵션 - 디폴트는 true):
+ lazy="false" 설정은 lazy 페칭을 사용불가능하게 만든다.
+
+
+
+
+
+
+ 이 매핑 방도에는 판별자 컬럼이나 키 컬럼이 필요하지 않다.
+
+
+
+ 상속 매핑들에 대한 정보는 을 보라.
+
+
+
+
+
+ join
+
+
+ <join> 요소를 사용하면, 한 개의 클래스의 프로퍼티들을 몇 개의 테이블들로 매핑시키는 것이
+ 가능하다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ...
+]]>
+
+
+
+
+ table: 조인된 테이블의 이름.
+
+
+
+
+ schema (옵션): 루트 <hibernate-mapping> 요소에
+ 의해 지정된 스키마 이름을 오버라이드 시킨다
+
+
+
+
+ catalog (옵션): 루트 <hibernate-mapping> 요소에
+ 의해 지정된 카타록 이름을 오버라이드 시킨다.
+
+
+
+
+ fetch (옵션 - 디폴트는 join):
+ join으로 설정될 경우, 디폴트로 Hibernate는 하나의 클래스 또는 그것의 슈퍼 클래스들에 의해
+ 정의된 <join>을 검색하는데 inner join을 사용하고 서브클래스에 의해 정의된
+ <join>을 검색하는데 outer join을 사용할 것이다. 만일 select로
+ 설정할 경우, Hibernate는 서브클래스 상에 정의된 <join>에 대해 sequential
+ select를 사용할 것이고, 그것은 한 행이 서브클래스의 인스턴스를 표현하는 것으로 판명되는 경우에만 명령이 내려질 것이다.
+ inner join들은 여전히 클래스와 그것의 슈퍼클래스들에 의해 정의된 <join>을 검색하는데
+ 사용될 것이다.
+
+
+
+
+ inverse (옵션 - 디폴트는 false):
+ 이용 가능할 경우, Hibernate는 이 조인에 의해 정의된 프로퍼티들을 삽입시키거나 업데이트하려고 시도하지
+ 않을 것이다.
+
+
+
+
+ optional (옵션 - 디폴트는 false):
+ 이용 가능할 경우, Hibernate는 이 조인에 의해 정의된 프로퍼티들이 null이 아닐 경우에만 한 행을 삽입시킬 것이고
+ 그 프로퍼티들을 검색하는데 outer join을 항상 사용할 것이다.
+
+
+
+
+
+
+ 예를 들어, (모든 프로퍼티들에 대해 value 타입 의미를 유지하면서) 개인의 주소 정보는 별도의 테이블에 매핑될 수 있다:
+
+
+
+
+ ...
+
+
+
+
+
+
+
+ ...]]>
+
+
+ 이 특징은 자주 리거시 데이터 모형들에 대해서만 유용하고, 우리는 클래스들과 잘 정제된 도메인 모형 보다 더 적은 테이블들을
+ 권장한다. 하지만 뒷 부분에 설명되어 있듯이, 그것은 하나의 계층구조 내에 있는 상속 매핑 방도들 사이를 전환하는 것에 유용하다.
+
+
+
+
+
+ key
+
+
+ 우리는 지금까지 몇 번 나타났던 <key> 요소를 보았다. 그것은 부모 매핑 요소가 새로운 테이블에
+ 대한 조인을 정의하는 어느 곳에서나 나타나고, 그것은 조인된 테이블의 foreign 키를 정의하고, 그것은 원래의 테이블의
+ 프라이머리 키를 참조한다.
+
+
+
+
+
+
+
+
+
+
+
+ ]]>
+
+
+
+
+ column (옵션):
+ foreign key 컬럼의 이름. 이것은 또한 내포된 <column> 요소(들)에 의해 지정될 수 있다.
+
+
+
+
+ on-delete (옵션 - 디폴트는 noaction):
+ foreign key 컨스트레인트가 데이터베이스 레벨의 cascade delete를 사용가능하도록 할 것인지 여부를 지정한다.
+
+
+
+
+ property-ref (옵션):
+ foreign key가 원래의 테이블의 프라이머리 키가 아닌 컬럼들을 참조함을 지정한다. (리거시 데이터에 제공됨.)
+
+
+
+
+ not-null (옵션):
+ foreign 키 컬럼들이 not null 임를 지정한다(이것은 foreign 키가 또한 프라이머리 키의 부분일 때마다 함축된다).
+
+
+
+
+ update (옵션):
+ foreign 키가 결코 업데이트되지 않아야 함을 지정한다(이것은 foreign 키가 또한 프라이머리 키의 부분일 때마다
+ 함축된다).
+
+
+
+
+ unique (옵션):
+ foreign 키가 유일 컨스트레인트를 가져야 함을 지정한다 (이것은 foreign 키가 또한 프라이머리 키의 부분일
+ 때마다 함축된다).
+
+
+
+
+
+
+ 우리는 delete 퍼포먼스가 중요한 시스템들에 대해 권장하고, 모든 키들은 on-delete="cascade"로
+ 정의되고, Hibernate는 많은 DELETE 문장들 대신에, 데이터베이스 레벨의
+ ON CASCADE DELETE 컨스트레인트를 사용할 것이다. 이 특징은 Hibernate의 통상적인 버전화된
+ 데이터에 대한 optimistic 잠금 방도를 무시한다는 점을 알고 있어라.
+
+
+
+ not-null 속성과 update 속성들은 단방향 one to many 연관관계를 매핑할 때
+ 유용하다. 만일 당신이 단방향 one to many를 null이 허용되지 않는 foreign 키로 매핑할 경우, 당신은
+ <key not-null="true">를 사용하여 그 키 컬럼을 선언해야 한다.
+
+
+
+
+
+ column 요소와 formula 요소
+
+ column 속성을 허용하는 임의의 매핑 요소는 대안적으로 하나의 <column> 서브요소를 수용할 것이다.
+ 비슷하게 <formula>는 formula 속성에 대한 대안이다.
+
+
+ ]]>
+
+ SQL expression]]>
+
+
+ column 속성과 formula 속성은 예를 들어 신종 조인 조건들을 표현하기 위해
+ 동일한 property 또는 연관관계 매핑 내에 결합될 수 있다.
+
+
+
+
+ 'MAILING'
+]]>
+
+
+
+
+ import
+
+
+ 당신의 어플리케이션이 동일한 이름을 가진 두 개의 영속 클래스들을 갖고, 당신이 Hibernate 질의들 내에서 전체 수식어가 붙은
+ (패키지)이름을 지정하는 것을 원하지 않는다고 가정하자. 클래스들은 auto-import="true"에 의존하기
+ 보다 명시적으로 "임포트 될 " 것이다. 당신은 심지어 명시적으로 매핑되지 않는 클래스들과 인터페이스들을 임포트 시킬 수(가져오기 할 수)
+ 있다.
+
+
+ ]]>
+
+
+
+
+
+
+ ]]>
+
+
+
+ class: 임의의 Java 클래스의 전체 수식어가 붙은 클래스 이름.
+
+
+
+
+ rename (옵션 - 디폴트는 수식어가 붙지 않은 클래스 이름):
+ 질의 언어 내에서 사용될 이름.
+
+
+
+
+
+
+
+
+ any
+
+
+ 하나 이상의 프로퍼티 매핑 타입이 존재한다. <any> 매핑 요소는 여러 테이블들로부터 클래스들에
+ 대한 하나의 다형성 연관관계를 정의한다. 이 매핑 타입은 언제나 하나 이상의 컬럼을 필요로 한다. 첫 번째 컬럼은 연관된 엔티티의
+ 타입을 보관한다. 나머지 컬럼들은 식별자를 보관한다. 이런 종류의 연관관계들에 대해 foreign key 컨스트레인트를 지정하는 것이
+ 불가능해서, 이것은 (다형성) 연관관계들을 매핑하는 통상적인 방법으로서 가장 확실한 수단이 아니다. 당신은 매우 특별한 경우들
+ (예를 들어 감사 로그들, 사용자 세션 데이터 등)에서만 이것을 사용해야 한다.
+
+
+
+ meta-type 속성은 어플리케이션으로 하여금 데이터베이스 컬럼 값들을 id-type에
+ 의해 지정된 타입의 식별자 프로퍼티들을 가진 영속 클래스들로 매핑시키는 맞춤형 타입을 지정하도록 한다. 당신은 meta-type의
+ 값들로부터 클래스 이름들로의 매핑을 지정해야 한다.
+
+
+
+
+
+
+
+
+]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ .....
+
+
+ .....
+]]>
+
+
+
+ name: 프로퍼티 이름.
+
+
+
+
+ id-type: 식별자 타입.
+
+
+
+
+ meta-type (옵션 - 디폴트는 string):
+ discriminator 매핑에 허용되는 임의의 타입.
+
+
+
+
+ cascade (optional- defaults to none):
+ cascade 스타일.
+
+
+
+
+ access (옵션 - 디폴트는 property):
+ Hibernate가 프로퍼티 값에 접근하는데 사용할 방도.
+
+
+
+
+ optimistic-lock (옵션 - 디폴트는 true):
+ 이 프로퍼티에 대한 업데이트들이 optimistic 잠금 획득을 필요로 하는지 여부를 지정한다. 달리 말해,
+ 이 프로퍼티가 dirty일 경우에 버전증가가 발생할 것인지 여부를 정의한다.
+
+
+
+
+
+
+
+
+
+
+ Hibernate 타입들
+
+
+ 엔티티들과 값들
+
+
+ 영속 서비스에 관한 여러 Java 언어-레벨의 객체들을 이해하기 위해, 우리는 그것들을 다음 두 개의 그룹들로 분류할 필요가 있다:
+
+
+
+ entity는 엔티티에 대한 참조들을 보관하는 임의의 다른 객체들과는 독립적으로 존재한다. 참조되지 않은
+ 객체가 쓰레기 수집되는 통상의 자바 모형과 이것은 대조적이다. (저장들과 삭제들이 부모 엔티티로부터 그것의 자식으로의 케스케이드
+ 되는 경우를 제외하면) 엔티티들은 명시적으로 저장되고 삭제되어야 한다. 이것은 도달 가능성(reachablity)에 의한 객체 영속성의
+ ODMG 모형과는 다르다 - 그리고 어플리케이션 객체들이 대형 시스템들에서 대개 어떻게 사용되는가에 훨씬 더 가깝게 대응한다.
+ 엔티티들은 순환 참조와 공유 참조들을 지원한다. 그것들 또한 버전화 될 수 있다.
+
+
+
+ 엔티티의 영속 상태는 다른 엔티티들에 대한 참조들과 value 타입들로 구성된다. 값들은 원시 타입들,
+ 콜렉션들(하나의 콜렉션 내부에 있지 않는 것들), 컴포넌트들, 그리고 어떤 불변의 객체들이다. entities와는 달리, (특별한
+ 콜렉션들과 컴포넌트들에서) 값들은 도달가능성(reachability)에 의해 영속화 되고 삭제 된다.
+ value 객체들(과 원시 타입들)이 그것들의 포함하는 엔티티에 따라 영속화 되고 삭제 되므로, 그것들은 독립적으로 버전화 되지
+ 않는다. 값들은 독립적인 엔티티를 갖지 않아서, 그것들은 두 개의 엔티티들이나 콜렉션들에 의해 공유될 수 없다.
+
+
+
+ 지금까지 우리는 엔티티들을 참조하기 위해 "영속 클래스"를 사용해 왔다. 우리는 그것을 계속 사용할 것이다. 하지만 엄격히 말해,
+ 영속 상태를 가진 모든 사용자 정의 클래스들은 엔티티들이 아니다. 컴포넌트는 value 의미를 가진
+ 사용자 정의 클래스이다. java.lang.String 타입의 자바 프로퍼티는 또한 value 의미를 갖는다.
+ 이 정의가 주어지면, 우리는 JDK에 의해 제공된 모든 타입들(클래스들)이 자바에서 value 타입 의미를 갖고, 반면에 사용자 정의
+ 타입들은 엔티티 또는 type 의미로서 매핑된다고 말할 수 있다. 이 판단은 어플리케이션 개발자에게 달려 있다. 도메인 모형에서
+ 엔티티 클래스에 대한 좋은 힌트는 그 클래스의 하나의 인스턴스에 대한 공유된 참조들인 반면에, composition이나 aggregation은
+ 대개 value 타입으로 변환된다.
+
+
+
+ 우리는 문서를 통해 두 개념들을 다시 고찰할 것이다.
+
+
+
+ 도점점은 Java type 시스템(과 엔티티들 및 value 타입들에 대한 개발자의 정의)를 SQL/데이터베이스 type 타입으로 매핑하는
+ 것이다. 두 시스템들 사이의 다리는 Hibernate에 의해 제공된다: 엔티티들의 경우 우리는 <class>,
+ <subclass> 등을 사용한다.value 타입들의 경우 우리는 대개type 속성을 가진
+ <property>, <component> 등을 사용한다. 이 속성의 값은
+ Hibernate 매핑 타입의 이름이다. Hibernate는 (표준 JDK value 타입들에 대해) 많은 매핑들을
+ 제공한다. 나중에 보게 되듯이, 당신은 당신 자신의 매핑 타입들을 작성할 수 있고 마찬가지로 당신의 맞춤형 변환 방도들을 구현할 수
+ 있다.
+
+
+
+ 콜렉션들을 제외한 모든 미리 빌드된 Hibernate 타입들은 null 의미를 지원한다.
+
+
+
+
+
+ 기본 value 타입들
+
+
+ 미리-만들어진 기본 매핑 타입들은 대략 다음과 같이 카테고리로 분류된다
+
+
+
+ integer, long, short, float, double, character, byte,
+ boolean, yes_no, true_false
+
+
+ 자바 원시타입들이나 wrapper 클래스들로부터 적절한(벤더-지정적인) SQL 컬럼 타입들로의 타입 매핑.
+ boolean, yes_no와 true_false는
+ Java boolean이나 java.lang.Boolean에 대한
+ 모든 대체적인 인코딩들이다.
+
+
+
+
+ string
+
+
+ java.lang.String으로부터 VARCHAR
+ (또는 Oracle VARCHAR2)로의 타입 매핑.
+
+
+
+
+ date, time, timestamp
+
+
+ java.util.Date와 그것의 서브클래스로부터 SQL 타입들인
+ DATE, TIME, TIMESTAMP
+ (또는 등가물)로의 타입 매핑들.
+
+
+
+
+ calendar, calendar_date
+
+
+ java.util.Calendar로부터 SQL 타입들인
+ TIMESTAMP, DATE (또는 등가물)로의 타입 매핑들.
+
+
+
+
+ big_decimal, big_integer
+
+
+ java.math.BigDecimal과 java.math.BigInteger로부터
+ NUMERIC (또는 Oracle NUMBER)로의 타입 매핑들.
+
+
+
+
+ locale, timezone, currency
+
+
+ java.util.Locale, java.util.TimeZone, 그리고
+ java.util.Currency로부터 VARCHAR(또는 Oracle
+ VARCHAR2)로의 타입 매핑. Locale과 Currency의
+ 인스턴스들은 그것들의 ISO 코드들로 매핑된다. TimeZone의 인스턴스들은 그것들의
+ ID로 매핑된다.
+
+
+
+
+ class
+
+
+ java.lang.Class로부터 VARCHAR (또는 Oracle
+ VARCHAR2)로의 타입 매핑. Class는 그것의 전체
+ 수식어가 붙은 이름으로 매핑된다.
+
+
+
+
+ binary
+
+
+ byte 배열들을 적절한 SQL binary 타입으로 매핑시킨다.
+
+
+
+
+ text
+
+
+ long Java 문자열을 SQL CLOB 또는 TEXT 타입으로
+ 매핑시킨다
+
+
+
+
+ serializable
+
+
+ serializable Java 타입들을 적절한 SQL binary 타입으로 매핑시킨다. 당신은 또한 디폴트로 기본 타입이
+ 아닌 serializable 자바 클래스 또는 인터페이스의 이름을 가진 Hibernate 타입 serializable을
+ 나타낼 수도 있다.
+
+
+
+
+ clob, blob
+
+
+ java.sql.Clob와 java.sql.Blob JDBC 클래스들에 대한 타입 매핑들.
+ 이들 타입들은 몇몇 어플리케이션들에서는 불편하다. 왜냐하면 blob 또는 clob 객체는 트랜잭션 외부에서 재사용될 수 없기
+ 때문이다.(게다가 드라이버 지원이 비일관적이고 페치되어야 한다)
+
+
+
+
+
+
+
+
+ 엔트리들과 콜렉션들의 유일 식별자들은 binary, blob 그리고 clob를
+ 제외한 기본 타입 중 어느 것일 수 있다. (Composite 식별자들이 또한 허용된다. 아래를 보라.)
+
+
+
+ 기본 value 타입들은 org.hibernate.Hibernate에 정의되어 있는 대응하는
+ Type 상수들을 갖는다. 예를 들어, Hibernate.STRING은
+ string 타입을 표현한다.
+
+
+
+
+
+ 맞춤형 value 타입들
+
+
+ 개발자들이 그들 자신들의 value 타입들을 생성시키는 것이 상대적으로 쉽다. 예를 들어, 당신은
+ java.lang.BigInteger 타입의 프로퍼티들을 VARCHAR 컬럼들로
+ 영속화 시키고자 원할 수 있다. Hibernate는 이것을 위한 미리 만들어진 타입을 제공하지 않는다. 그러나 맞춤형 타입들은
+ 프로퍼티(또는 콜렉션 요소)를 하나의 테이블 컬럼으로의 매핑하는 것에 제약되지 않는다. 따라서 예를 들어, 당신은
+ FIRST_NAME, INITIAL, SURNAME 컬럼들로
+ 영속화 되는 java.lang.String 타입의 자바 프로퍼티getName()/
+ setName()를 가질 수 있다.
+
+
+
+ 맞춤형 타입을 구현하려면, org.hibernate.UserType 또는 org.hibernate.CompositeUserType을
+ 구현하고 그 타입의 전체 수식어가 붙은 클래스명을 사용하여 프로퍼티들을 선언하라. 가능한 종류의 것들을 보려면
+ org.hibernate.test.DoubleStringType을 체크하라.
+
+
+
+
+
+]]>
+
+
+ 하나의 프로퍼티를 여러 개의 컬럼들로 매핑시키는 <column> 태그의 사용을 주목하라.
+
+
+
+ CompositeUserType, EnhancedUserType,
+ UserCollectionType, 그리고 UserVersionType 인터페이스들은
+ 더 많은 특화된 사용들을 위한 지원을 제공한다.
+
+
+
+ 당신은 매핑 파일 속에 UserType에 대한 파라미터들을 제공할 수도 있다. 이것을 행하기 위해,
+ 당신의 UserType은 org.hibernate.usertype.ParameterizedType
+ 인터페이스를 구현해야 한다. 당신의 맞춤형 타입에 파라미터들을 제공하기 위해, 당신은 당신의 매핑 파일들 속에
+ <type> 요소를 사용할 수 있다.
+
+
+
+
+ 0
+
+]]>
+
+
+ UserType은 이제 그것에 전달된 Properties 객체로부터
+ default로 명명된 파라미터에 대한 값을 검색할 수 있다.
+
+
+
+ 만일 당신이 매우 자주 어떤 UserType을 사용할 경우, 그것은 그것에 대한 더 짧은 이름을 정의하는 것이 유용할 수 있다.
+ <typedef> 요소를 사용하여 이것을 행할 수 있다. Typedef들은 이름을 맞춤형 타입에
+ 할당하고, 또한 만일 그 타입이 파라미터화 된 경우에 디폴트 파라미터 값들의 리스트를 포함할 수도 있다.
+
+
+
+ 0
+]]>
+
+ ]]>
+
+
+ property 매핑 상에 type 파라미터들을 사용함으로써 경우에 맞게 typedef 내에 제공된 파라미터들을 오버라이드 시키는 것이
+ 가능하다.
+
+
+
+ 비록 Hibernate의 풍부한 범위의 미리 만들어진 타입들과 컴포넌트들에 대한 지원이 당신이 가끔 맞춤형 타입을 사용할 필요가
+ 거의 없을 것임을 의미할 지라도, 그럼에도 불구하고 그것은 당신의 어플리케이션에서 자주 발생하는 (엔티티가 아닌) 클래스들에 대해
+ 맞춤형 타입들을 사용하는 좋은 형식으로 간주된다. 예를 들어 MonetaryAmount 클래스는 비록 그것이
+ 컴포넌트로서 쉽게 매핑될 수 있을지라도, CompositeUserType에 대한 좋은 후보이다. 이것에 대한
+ 하나의 동기는 추상화이다. 맞춤형 타입으로, 당신의 매핑 문서들은 화폐 값들을 표현하는 당신의 방법에서 가능한 변경들에 대해 장차
+ 검증될 것이다.
+
+
+
+
+
+
+
+ 하나의 클래스를 한 번 이상 매핑하기
+
+ 하나의 특정한 영속 클래스에 대해 하나 이상의 매핑을 제공하는 것이 가능하다. 이 경우에 당신은 두 개의 매핑된 엔티티들의
+ 인스턴스들 사이를 명확하게 하기 위해 하나의 엔티티 이름을 지정해야 한다. (디폴트로, 엔티티
+ 이름은 클래스 이름과 동일한 것이다.) Hibernate는 영속 객체들에 대해 작업할 때, 질의들을 작성할 때, 또는 명명된 엔티티에
+ 대한 연관들을 매핑할 때 당신으로 하여금 엔티티 이름을 지정하도록 한다.
+
+
+
+ ...
+
+
+
+
+
+
+
+ ...
+
+]]>
+
+
+ 연관들은 이제 class 대신에 entity-name을 사용하여 어떻게 지정되는지를
+ 주목하라.
+
+
+
+
+
+ SQL 인용부호 표시된 식별자들
+
+ 당신은 매핑 문서 내에서 테이블 또는 컬럼 이름을 역인용기호(`)들 속에 넣어서 생성된 SQL에서 식별자를 인용부호 처리하도록
+ Hibernate에게 강제할 수도 있다. Hibernate는 SQL Dialect에 대해 정확한 인용 스타일을 사용할
+ 것이다(대개 이중 인용부호 이지만, SQL Server의 경우에는 모난 괄호들이고 MySQL의 경우에는 역인용부호(`)).
+
+
+
+
+
+ ...
+]]>
+
+
+
+
+
+ Metadata 대안들
+
+
+ XML은 모든 사람들을 위한 것이 아니지만, Hibernate에서 O/R 매핑 메타데이터를 정의하는 몇몇 대안적인 방법들이 존재한다.
+
+
+
+ XDoclet 마크업 사용하기
+
+
+ 많은 Hibernate 사용자들은 XDoclet @hibernate.tags를 사용하여 소스 코드 속에
+ 직접 매핑 정보를 삽입시키는 것을 선호한다. 우리는 이 문서에서 이 접근법을 다루지 않을 것이다. 왜냐하면 그것은
+ 엄격하게는 XDoclet의 부분으로 간주되기 때문이다. 하지만 우리는 XDoclet 매핑들을 가진 Cat
+ 클래스에 관한 다음 예제를 포함한다.
+
+
+
+
+
+ XDoclet과 ibernate에 관한 추가 예제들은 Hibernate 웹 사이트를 보라.
+
+
+
+
+
+ JDK 5.0 Annotations 사용하기
+
+
+ JDK 5.0은 언어 레벨에서 XDoclet-스타일의 주석들, type-safe와 컴파일 시 체킹을 도입했다. 이 메커니즘은 XDoclet
+ 주석들 보다 더 강력하며 도구들과 IDE들에 의해 더 좋게 지원된다. 예를 들어 IntelliJ IDEA는 JDK 5.0 주석들에 대한
+ 자동-완성 기능과 구문 강조를 지원한다. EJB 명세서의 새로운 개정판(JSR-220)은 엔티티 빈즈에 대한 프라이머리 메타데이터
+ 메커니즘으로서 JDK 5.0 Annotations을 사용한다. Hibernate3는 JSR-220(영속 API)의 EntityManager를
+ 구현하고, 매핑 메타데이터에 대한 지원은 별도의 내려받기로서 Hibernate Annotations 패키지를
+ 통해 이용 가능하다. EJB3 (JSR-220)과 Hibernate3 metadata 양자가 지원된다.
+
+
+
+ 다음은 EJB 엔티티 빈으로서 주석이 붙은 POJO 클래스에 관한 예제이다:
+
+
+ orders;
+
+ // Getter/setter and business methods
+}]]>
+
+
+ JDK 5.0 Annotations(그리고 JSR-220)에 대한 지원은 여전히 작업이 진행 중이고 완성되지 않았음을 노트하라. 상세한 것은
+ Hibernate Anotations를 참조하라.
+
+
+
+
+
+
+
diff --git a/reference/ko/modules/batch.xml b/reference/ko/modules/batch.xml
new file mode 100644
index 0000000000..07f7a8b4e1
--- /dev/null
+++ b/reference/ko/modules/batch.xml
@@ -0,0 +1,178 @@
+
+ Batch 처리
+
+
+ Hibernate를 사용하여 데이터베이스 내에서 100 000 개의 행들을 삽입시키는 본래의 접근법은 다음과 같다:
+
+
+
+
+
+ 이것은 50 000번째 행 가까운 곳에서 OutOfMemoryException으로 떨어질 것이다. 그것은 Hibernate가
+ session-level 캐시 속에 모든 새로이 삽입된 Customer 인스턴스들을 캐시시키기 때문이다.
+
+
+
+ 이 장에서 우리는 이 문제를 피하는 방법을 당신에게 보여줄 것이다. 하지만 먼저 당신이 배치 처리를 행하는 중이라면, 당신이 적당한 퍼포먼스를
+ 성취하려고 할 경우에 당신이 JDBC 배치 사용을 가능하게 하는 것은 절대적으로 필요하다. JDBC 배치 사이즈를 적당한 숫자(10-50)로 설정하라:
+
+
+
+
+
+ 당신은 또한 second-level 캐시를 가진 상호작용이 완전하게 불가능한 프로세스 내에서 이런 종류의 작업을 행하고 싶어할 수도 있다:
+ You also might like to do this kind of work in a process where interaction with
+ the second-level cache is completely disabled:
+
+
+
+
+
+ Batch inserts
+
+
+ 새로운 객체들을 영속화 시킬 때, 당신은 first-level 캐시의 사이즈를 제어하기 위해 세션을 정기적으로 flush()
+ 시키고 나서 clear() 시켜야 한다.
+
+
+
+
+
+
+
+ Batch updates
+
+
+ 데이터 검색과 업데이트의 경우 동일한 개념들이 적용된다. 게다가 당신은 많은 데이터 행들을 반환하는 질의들에 대해 서버-측 커서들의 장점을
+ 취하는데 scroll()을 사용할 필요가 있다.
+
+
+
+
+
+
+
+ 대량 update/delete
+
+
+ 이미 논의했듯이, 자동적이고 투명한 객체/관계형 매핑은 객체 상태에 대한 관리에 관계된다. 이것은 객체 상태가 메모리 내에서 이용 가능함을
+ 의미하므로, (SQL UPDATE와 DELETE를 사용하여) 데이터베이스 내에서 직접 데이터를
+ 업데이트하거나 삭제하는 것은 메모리 내 상태에 영향을 주지 않을 것이다. 하지만 Hibernate는 Hibernate Query Language를 통해
+ 수행되는 대량 SQL-스타일의 UPDATE와 DELETE 문장 실행을 위한 방법들을 제공한다.
+ (HQL).
+
+
+
+ UPDATE와 DELETE 문장들의 유사-구문은 다음과 같다:
+ ( UPDATE | DELETE ) FROM? ClassName (WHERE WHERE_CONDITIONS)?. 노트할 몇 가지 :
+
+
+
+
+
+ from-절에서, FROM 키워드는 옵션이다
+
+
+
+
+ from-절 내에 명명된 한 개의 클래스가 오직 존재할 수 있고, alias를 가질 수 없다.
+
+
+
+
+ join들은 (함축적이든 명시적이든) 대량 HQL 질의 속에 지정될 수 없다. 서브-질의들이 where-절 속에서 사용될 수 있다.
+
+
+
+
+ where-절 또한 옵션이다.
+
+
+
+
+
+ 하나의 예제로서, 한 개의 HQL UPDATE를 실행하기 위해, Query.executeUpdate()
+ 메소드를 사용하라:
+
+
+
+
+
+ 한 개의 HQL DELETE를 실행하기 위해, 동일한 Query.executeUpdate() 메소드를
+ 사용하라(그 메소드는 JDBC의 PreparedStatement.executeUpdate()에 친숙한 사람들을 위해 명명되어 있다):
+
+
+
+
+
+ Query.executeUpdate() 메소드에 의해 반환되는 int 값은 그 오퍼레이션에 의해
+ 영향받은 엔티티들의 개수를 나타낸다. 이것이 데이터베이스 내에서 영향받은 행들의 개수와 상관이 있는지 없는지 여부를 살펴보자. HQL
+ 대량 오퍼레이션은 예를 들어 joined-subclass의 경우에 실행 중인 여러 개의 실제 SQL 문장들로 귀결될 수 있다. 반환되는 숫자는
+ 그 문장에 의해 영향받은 실제 엔티티들의 개수를 나타낸다. joined-subclass 예제로 되돌아가면, 서브 클래스들 중 하나에 대한 삭제는
+ 단지 그 서브클래스가 매핑되어 있는 테이블에 대한 삭제 뿐만 아니라 또한 "루트" 테이블과 상속 계층에서 더 내려온 잠정적으로
+ 조인된-서브클래스 테이블들에 대한 삭제들로 귀결될 수 있다.
+
+
+
+ 장래의 배포본들에서 전달될 대량 HQL 오퍼레이션들에 대한 몇 가지 제한들이 현재 존재함을 노트하라; 상세한 것은 JIRA 로드맵을 참조하라.
+
+
+
+
+
diff --git a/reference/ko/modules/best_practices.xml b/reference/ko/modules/best_practices.xml
new file mode 100644
index 0000000000..f286482e58
--- /dev/null
+++ b/reference/ko/modules/best_practices.xml
@@ -0,0 +1,204 @@
+
+ 최상의 실전 경험들
+
+
+
+ fine-grained 클래스들을 작성하고 <component>를 사용하여 그것들을 매핑하라.
+
+
+ street, suburb, state, postcode를
+ 캡슐화 시키는데 Address 클래스를 사용하라. 이것은 코드 재사용성을 촉진시키고 리팩토링을 단순화 시킨다.
+
+
+
+
+ 영속 클래스들에 대해 식별자 프로퍼티들을 선언하라.
+
+
+ Hibernate는 식별자 프로퍼티들을 옵션으로 만든다. 왜 우리가 그것들을 사용해야 하는가에 대한 모든 종류의 이유들이 존재한다.
+ 우리는 식별자들이 '합성(synthetic)'이 되는(비지니스 의미 없이 생성되는) 것을 권장한다.
+
+
+
+
+ 고유 키들을 식별하라.
+
+
+ 모든 엔티티들에 대해 고유 키들을 식별하고, <natural-id>를 사용하여 그것들을 매핑하라.
+ 고유 키를 구성하는 프로퍼티들을 비교하기 위해 equals()와 hashCode()를
+ 구현하라.
+
+
+
+ 각각의 클래스 매핑을 그것 자신의 파일 내에 위치지워라.
+
+
+ 하나의 한덩어리 매핑 문서를 사용하지 말라. com/eg/Foo.hbm.xml 파일 속에
+ com.eg.Foo를 매핑하라. 이것은 팀 환경에서 특히 좋은 의미를 준다.
+
+
+
+
+ 매핑들을 리소스들로서 로드시켜라.
+
+
+ 그것들이 매핑하는 클래스들에 따라서 매핑들을 배치하라
+
+
+
+
+ 질의 문자열들을 객관화 시키는 것을 고려하라.
+
+
+ 당신의 질의들이 ANSI 표준이 아닌 SQL 함수들을 호출하는 경우는 좋은 실전연습이다. 질의 문자열들을 매핑 파일들에다가
+ 외부화 시키는 것은 어플리케이션을 보다 이식성 있도록 만들어줄 것이다.
+
+
+
+
+ 바인드 변수들을 사용하라.
+
+
+ JDBC에서처럼, 상수 아닌 값들을 "?"로 대체시켜라. 질의 속에 상수 아닌 값을 바인드 시키는데 문자열 처리를 결코
+ 사용하지 말라! 더 좋게는 질의들 속에 명명된 파라미터들을 사용하는 것을 고려하라.
+
+
+
+
+ 당신 자신의 JDBC 커넥션들을 관리하지 말라.
+
+
+ Hibernate는 어플리케이션으로 하여금 JDBC 커넥션들을 관리하도록 한다. 이 접근법은 마지막 수단으로서 고려되어야 한다.
+ 만일 당신이 미리 만들어진 커넥션 프로바이더들을 사용할 수 없을 경우, org.hibernate.connection.ConnectionProvider에
+ 대한 당신 자신의 구현을 제공하는 것을 고려하라.
+
+
+
+
+ 맞춤형 타입 사용을 고려하라.
+
+
+ 당신이 자바 타입을 갖고 있고, 어떤 라이브러리로부터 말하고, 그것이 영속화 될 필요가 있지만 그것을 컴포넌트로서 매핑시키는데
+ 필요한 accessor들을 제공할 필요가 없다고 가정하자. 당신은 org.hibernate.UserType을 구현하는
+ 것을 고려해야 할 것이다. 이 접근법은 Hibernate 타입으로/으로부터 변환들을 구현하는 것으로부터 어플리케이션 코드를 자유롭게
+ 해준다.
+
+
+
+
+ 병목 지점들에서 수작업으로 코딩된 JDBC를 사용하라.
+
+
+ 시스템의 퍼포먼스가 중대한 영역들에서, 몇몇 종류의 오퍼레이션들은 직접적인 JDBC에서 이득을 본다. 그러나 당신이 어떤 것이 병목인지를
+ 알기 전까지 기다리길 바란다. 그리고 직접적인 JDBC가 반드시 더 빠르다고 가정하지 말라. 만일 당신이 직접적인
+ JDBC를 사용할 필요가 있을 경우, Hibernate Session을 열고 그 SQL 커넥션을 사용할 가치가 있다. 그 방법으로
+ 당신은 동일한 트랜잭션 방도와 기본 커넥션 프로바이더를 여전히 사용할 수 있다
+
+
+
+
+ Session flushing을 이해하라.
+
+
+ 시간이 지남에 따라 Session은 그것의 영속 상태를 데이터베이스와 동기화 시킨다. 만일 이 과정이 너무 자주 발생할 경우 퍼포먼스가
+ 영향을 받을 것이다. 당신은 때때로 자동적인 flushing을 사용 불가능하게 만들거나 특정 트랜잭션 내에서 질의들의 순서와 다른
+ 오퍼레이션들의 순서를 변경시켜서 불필요한 flushing을 최소화 시킬 수 있다.
+
+
+
+
+ 3-tier 아키텍처에서, saveOrUpdate() 사용을 고려하라.
+
+
+ servlet / session 빈 아키텍처를 사용할 때, 당신은 sesson bean 내에 로드된 영속 객체들을 서블릿/JSP 계층으로/으로부터
+ 전달할/받을 수 있다. 각각의 요청을 서비스하는데 새로운 세션을 사용하라. 객체들을 데이터베이스와 동기화 시키기 위해서
+ Session.merge() 또는 Session.saveOrUpdate()를 사용하라.
+
+
+
+
+ 2-tier 아키텍처에서, 수명이 긴 영속 컨텍스트들을 사용하는 것을 고려하라.
+
+
+ 데이터베이스 트랜잭션들은 최상의 가용성을 위해 가능한 한 짧아야 한다. 하지만 장기간 실행되는 어플리케이션 트랜잭션들,
+ 사용자의 뷰 관점에서 한 개의 단위 작업을 구현하는 것이 가끔 필수적이다. 하나의 어플리케이션 트랜잭션은 몇 개의 클라이언트 요청들과
+ 응답 주기들에 걸칠 수도 있다. 어플리케이션 트랜잭션들을 구현하는데 detached 객체들을 사용하는 것이 공통적이다. 2-티어 아키텍처에서
+ 매우 적절한 대안은 어플리케이션 트랜잭션의 전체 생명주기 동안에 한 개의 열려진 영속 접속 (세션)을 유지하는 것이고 각각의 요청의 끝에서
+ JDBC 커넥션을 간단하게 연결해제하고 차후의 요청의 시작 시에 다시 연결하는 것이다. 한 개 이상의 어플리케이션 트랜잭션을 가로질러서
+ 하나의 단일 세션을 결코 공유하지 말라. 공유할 경우에 당신은 실효성이 없는 데이터로 작업하게 될 것이다.
+
+
+
+
+ 예외상황들을 복구가능한 것으로서 다루지 말라.
+
+
+ 이것은 "최상의" 실전이 아닌 보다 필수적인 실전이다. 예외상황이 발생할 때, Transaction을 롤백시키고
+ Session을 닫아라. 만일 당신이 그렇게 하지 않을 경우, Hibernate는 메모리 내 상태가 영속 상태를 정확하게
+ 표현하는 것을 보증할 수 없다. 이 특별한 경우처럼, 만일 주어진 식별자를 가진 인스턴스가 데이터베이스 상에 존재하는지 여부를 결정하는데
+ Session.load()를 사용하지 말라; 대신에 Session.get() 또는 하나의 질의를
+ 사용하라.
+
+
+
+
+ 연관들에 대한 lazy 페칭을 선호하라.
+
+
+ eager 페칭을 관대하게 사용하라. second-level 캐시 내에 완전하게 보관되지 않을 것 같은 클래스들에 대한 대붑분의 연관들에
+ 대해 프락시들과 lazy 콜렉션들을 사용하라. 캐시된 클래스들에 대한 연관들의 경우, 이곳은 캐시 성공의 매우 높은 확률이 존재하는
+ 곳이며, lazy="false"를 사용하여 eager 페칭을 명시적으로 사용 불가능하게 하라. 한의 join 페칭이
+ 특정 쓰임새에 대해 적절할 때, 하나의 left join fetch를 가진 질의를 사용하라.
+
+
+
+
+
+ 페치되지 않은 데이터 문제점들을 피하기 위해 뷰 내에 열려진 세션(open session in view) 패턴 또는
+ 하나의 정리된 어셈블리 단계(assembly phase)를 사용하라.
+
+
+
+ Hibernate는 개발자들이 Data Transfer Objects (DTO)를 지루하게 작성하는 것으로부터
+ 자유롭게 해준다. 전통적인 EJB 아키텍처에서, DTO는 이중 용도로 기능한다: 첫 번째로 그것들은 엔티티 빈즈가 직렬화 가능하지 않는
+ 문제점에 대해 착수한다; 두 번째로 그것들은 뷰에 의해 사용되는 모든 데이터가 프리젠테이션 티어로 컨트롤을 반환하기 전에 DTO들 속으로
+ 페치되고 마샬링되는 어셈블리 단계를 암묵적으로 정의한다. Hibernate는 첫 번째 용도를 제거시킨다. 하지만 당신이 뷰 렌더링 프로세스를
+ 가로질러 열려져 있는 영속 컨텍스트(세션)을 보관할 준비가 되어 있지 않는 한, 당신은 여전히 어셈블리 단계를 필요로 할 것이다(detached
+ 객체들에서 이용가능한 데이터가 무엇인지에 대해 프리젠테이션 티어와 엄격하게 계약을 갖도록 당신의 비지니스 메소드들을 고려하라)
+ 이것은 Hibernate의 한계점이 아니다! 그것은 안전한 트랜잭션 데이터 접근의 필수 조건이다.
+
+
+
+
+ Hibernate에서 당신의 비지니스 로직을 추상화 시키는 것을 고려하라.
+
+
+ (Hibernate) 데이터 액세스 코드를 인터페이스 이면에 은폐시켜라. DAO와
+ Thread Local Session 패턴들을 결합시켜라. 당신은 심지어 UserType을
+ 통해 Hibernate에 연관된, 수작업으로 코딩된 JDBC로서 몇몇 클래스들을 영속화 시킬 수도 있다. (이 충고는 "충분히 큰"
+ 어플리케이션들에 대한 것이다; 그것은 5개의 테이블들을 가진 어플리케이션에 대해서는 적절하지 않다!)
+
+
+
+
+ 신종의 연관 매핑을 사용하지 말라.
+
+
+ 실제의 many-to-many 연관들에 대한 좋은 쓰임새들은 드물다. 대부분의 시간 동안 당신은 "연결 테이블" 내에 저장된 추가적인 정보를 필요로 한다.
+ 이 경우에, 매개하는 연결 클래스에 대해 두 개의 one-to-many 연관들을 사용하는 것이 훨씬 더 좋다. 사실 우리는 대부분의 연관들이 one-to-many와
+ many-to-one이라고 생각하며, 당신은 다른 연관 스타일을 사용할 때 주의해야 하고 그것이 진정 필수적인지를 당신 스스로 질문하라.
+
+
+
+
+ 양방향 연관들을 선호하라.
+
+
+ 단방향 연관들은 질의하기가 더 어렵다. 많은 어플리케이션에서, 거의 모든 연관들은 질의들 내에서 양 방향으로 네비게이트 가능해야 한다.
+
+
+
+
+
+
+
diff --git a/reference/ko/modules/collection_mapping.xml b/reference/ko/modules/collection_mapping.xml
new file mode 100644
index 0000000000..c89dbc9595
--- /dev/null
+++ b/reference/ko/modules/collection_mapping.xml
@@ -0,0 +1,1075 @@
+
+ 콜렉션 매핑
+
+
+ 영속 콜렉션들
+
+
+ 예를 들어 Hibernate는 영속 콜렉션-값을 가진 필드들이 인터페이스 타입으로서 선언될 것을 필요로 한다:
+
+
+
+
+
+ 실제 인터페이스는 java.util.Set, java.util.Collection,
+ java.util.List, java.util.Map, java.util.SortedSet,
+ java.util.SortedMap 또는 당신이 좋아하는 어떤 것일 수 있다!(여기서 "당신이 좋아하는 어떤 것"이란
+ 당신이 org.hibernate.usertype.UserCollectionType에 대한 구현을 작성해야 함을 의미한다.)
+
+
+
+ 우리가 HashSet의 인스턴스를 가진 인스턴스 변수를 초기화 시켰던 방법을 주목하라. 이것은 새로이
+ 초기화 된(비-영속) 인스턴스들을 가진 콜렉션 값 프로퍼티들을 초기화 시키는 최선의 방법이다. 당신이 -예를 들어
+ persist()를 호출하여- 인스턴스를 영속화 시킬 때 Hibernate는 실제로 HashSet을
+ Set에 대한 Hibernate 자신의 구현의 인스턴스로 대체시킬 것이다. 다음과 같은 오류들을 관찰하라:
+
+
+
+
+
+ Hibernate에 의해 도입된 영속 콜렉션들은 인터페이스 타입에 따라 HashMap, HashSet,
+ TreeMap, TreeSet 또는 ArrayList와 같이 행위한다.
+
+
+
+ 콜렉션 인스턴스들은 value 타입들을 가진 통상의 특징을 갖는다. 그것들은 영속 객체에 의해 참조될 때 자동적으로 영속화 되고
+ 참조 해제될 때 자동적으로 삭제된다. 만일 하나의 콜렉션이 하나의 영속 객체로부터 또 다른 영속 객체로 전달될 때, 그것의 요소들은
+ 하나의 테이블로부터 다른 테이블로 이동될 수 있다. 두 개의 엔티티들은 동일한 콜렉션 인스턴스에 대한 참조를 공유하지 않는다.
+ 기본 관계형 모형 때문에 콜렉션 값 프로퍼티들은 null 값 의미들을 지원하지 않는다; Hibernate는 null 콜렉션 참조와 공백의
+ 콜렉션 사이를 구별 짓지 않는다.
+
+
+
+ 당신은 이것의 어떤 것에 대해 너무 많이 걱정하지 않아도 될 것이다. 당신이 통상의 자바 콜렉션들을 사용하는 것과 동일한 방법으로
+ 영속 콜렉션들을 사용하라. 단지 당신이 양방향 연관관계들에 대한 의미를 확실히 이해하도록 하라(나중에 논의됨).
+
+
+
+
+
+ 콜렉션 매핑들
+
+
+ 콜렉션을 매핑하는데 사용되는 Hiberante 매핑 요소는 인터페이스의 타입에 의존한다. 예를 들어<set>
+ 요소는 Set 타입의 매핑 프로퍼티들에 사용된다
+
+
+
+
+
+
+
+
+]]>
+
+
+ <set>과는 별도로, 또한 <list>, <map>,
+ <bag>, <array>, 그리고 <map>
+ 매핑 요소들이 존재한다. <map> 요소가 대표적이다:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+ name 콜렉션 프로퍼티 이름
+
+
+
+
+ table (옵션 - 디폴트는 프로퍼티 이름)
+ 콜렉션 테이블의 이름(one-to-many 연관관계들에 대해서는 사용되지 않음)
+
+
+
+
+ schema (옵션)
+ 루트 요소 상에 선언된 스키마를 오버라이드 시키는 테이블 스키마의 이름
+
+
+
+
+ lazy (옵션 - 디폴트는 true)
+ lazy 페칭을 사용 불가능하도록 하고 그 연관이 항상 eagerly 페치됨을 지정하는데 사용될 수 있다
+ (배열들에 대해서는 이용 불가능함)
+
+
+
+
+ inverse (옵션 - 디폴트는 false)
+ 이 콜렉션을 양방향 연관관계의 "inverse" 끝(end)으로 표시한다
+
+
+
+
+ cascade (옵션 - 디폴트는 none)
+ 오퍼레이션들이 자식 엔티티들에 대해 케스케이드하는 것을 이용 가능하게 한다
+
+
+
+
+ sort (옵션)
+ natural 정렬 순서로 정렬된(sorted) 콜렉션 또는 주어진 comparator 클래스를 지정한다
+
+
+
+
+ order-by (옵션, JDK1.4에서만)
+ asc 또는 desc 옵션과 함께 Map,
+ Set 또는 bag의 반복 순서를 정의하는 테이블 컬럼(또는 컬럼들)을 지정한다
+
+
+
+
+ where (옵션)
+ 콜렉션을 검색하거나 제거할 때 사용될 임의적인 SQL WHERE 조건을 지정한다
+ (콜렉션이 오직 이용 가능한 데이터의 부분집합 만을 포함할 경우에 유용하다)
+
+
+
+
+ fetch (옵션, 디폴트는 select)
+ outer-join 페칭, sequential select 페칭, 그리고 sequential subselect 페칭 사이에서 선택하라.
+
+
+
+
+ batch-size (옵션, 디폴트는 1)
+ 이 콜렉션의 lazily fetching 인스턴스에 대해 "배치 사이즈"를 지정하라.
+
+
+
+
+ access (옵션 - 디폴트는 property):
+ Hibernate가 프로퍼티 값에 접근하는데 사용할 방도.
+
+
+
+
+ optimistic-lock (옵션 - 디폴트는 true):
+ 콜렉션의 상태에 대한 변경들이 소유하는 엔티티의 버전의 증가로 귀결될 것인지를 지정한다.
+ (one to many 연관들에 대해, 이 설정을 사용 불가능하게 하는 것이 종종 합당하다.)
+
+
+
+
+
+
+ 콜렉션 foreign 키들
+
+
+ 콜렉션 인스턴스들은 그 콜렉션을 소유하는 엔티티의 foreign 키에 의해 데이터베이스 내에서 구별지워진다. 이 foreign 키는
+ 그 콜렉션 테이블의 콜렉션 키 컬럼 (또는 컬럼들)로서 참조된다. 그 콜렉션 키 컬럼은
+ <key> 요소에 의해 매핑된다.
+
+
+
+ foreign 키 컬럼에 대한 null 허용 가능 컨스트레인트가 존재할 수 있다. 대부분의 콜렉션들에 대해, 이것이 당연히 수반된다.
+ 단방향 one to many 연관들의 경우, foreign 키는 디폴트로 null 허용 가능하여서, 당신은 not-null="true"를
+ 지정할 필요가 있을 수 있다.
+
+
+ ]]>
+
+
+ foreign 키 컨스트레인트는 ON DELETE CASCADE를 사용할 수도 있다.
+
+
+ ]]>
+
+
+ <key> 요소에 대한 전체 정의는 앞 장을 보라.
+
+
+
+
+
+ 콜렉션 요소들
+
+
+ 콜렉션들은 모든 기본 타입들, 컴포넌트들, 그리고 물론 다른 엔티티들에 대한 참조들을 포함하여 거의 대부분의
+ 어떤 다른 Hibernate 타입을 포함할 수도 있다. 이것은 중요한 구분이다: 콜렉션 내에 있는 객체는 "값(value)"
+ 의미로 처리될 수도 있거나(그것의 생명주기는 콜렉션 소유자에 의존한다) 그것은 그것 자신의 생명주기를 가진
+ 또 다른 엔티티에 대한 참조일 수 있다. 후자의 경우, 두 개의 객체들 사이의 "링크" 만이 그 콜렉션에 의해 소유된
+ 상태로 간주된다.
+
+
+
+ 포함된 타입은 콜렉션 요소 타입으로서 불려진다. 콜렉션 요소들은 <element>
+ 또는 <composite-element>에 의해 매핑되거나, 엔티티 참조들의 경우에
+ <one-to-many> 또는 <many-to-many>로서
+ 매핑된다. 앞의 두 개는 value 의미를 가진 요소들을 매핑시키고, 뒤의 두개는 엔티티 연관들을 매핑하는데 사용된다.
+
+
+
+
+
+ 인덱싱 된 콜렉션들
+
+
+ set 과 bag 의미들을 가진 것들을 제외하면, 모든 콜렉션 매핑들은 콜렉션 테이블 내에 인덱스 컬럼-
+ 배열 인덱스, 또는 List 인덱스 또는 Map 키로 매핑되는 컬럼-을 필요로 한다.
+ Map의 인덱스는 <map-key>로 매핑된, 어떤 기본 타입일 수 있고,
+ 그것은 <map-key-many-to-many>로 매핑된 엔티티 참조일 수 있거나, 그것은
+ <composite-map-key>로 매핑된 composite 타입일 수 있다. 배열 또는 리스트의 인덱스는
+ 항상 integer 타입이고 <list-index> 요소를 사용하여 매핑된다.
+ 매핑된 컬럼은 순차적인 정수들을 포함한다(디폴트로 0에서 시작하는 번호가 붙여짐).
+
+
+
+
+
+
+
+ ]]>
+
+
+
+ column_name (필수):
+ 콜렉션 인덱스 값들을 보관하는 컬럼의 이름.
+
+
+
+
+ base (옵션, 디폴트는 0):
+ 리스트 또는 배열의 첫 번째 요소에 대응하는 인덱스 컬럼의 값.
+
+
+
+
+
+
+
+
+
+
+
+ ]]>
+
+
+
+ column (옵션):
+ 콜렉션 인덱스 값들을 보관하는 컬럼의 이름.
+
+
+
+
+ formula (옵션):
+ map의 키를 평가하는데 사용되는 SQL formula.
+
+
+
+
+ type (필수): The type of the map 키들의 타입
+
+
+
+
+
+
+
+
+
+
+
+ ]]>
+
+
+
+ column (옵션):
+ 콜렉션 인덱스 값들에 대한 foreign 키 컬럼의 이름.
+
+
+
+
+ formula (옵션):
+ map의 foreign 키를 평가하는데 사용되는 SQL formula.
+
+
+
+
+ class (필수): map 키로서 사용되는 엔티티 클래스.
+
+
+
+
+
+
+
+ 만일 당신의 테이블이 인덱스 컬럼을 가지 않고, 당신이 여전히 프로퍼티 타입으로서 List를 사용하고자
+ 원할 경우, 당신은 그 프로퍼티를 Hibernate <bag>으로서 매핑해야 한다. bag이
+ 데이터베이스로부터 검색될 때 그것은 그것의 순서를 보유하지 않지만, 그것은 선택적으로 정렬(sorting)되거나 ordering될
+ 수도 있다.
+
+
+
+
+
+ 많은 공통된 관계형 모형들을 다루는, 콜렉션들에 대해 생성될 수 있는 매핑들의 영역이 꽤 존재한다. 여러가지 매핑 선언들이 데이터베이스
+ 테이블들로 변환되는 방법을 당신이 느끼려면 스키마 생성 도구로 실험할 것을 우리는 제안한다.
+
+
+
+ 값들을 가진 콜렉션들과 many-to-many 연관들
+
+
+ 어떤 값들을 가진 콜렉션 또는 many-to-many 연관은 foreign 키 컬럼이나 컬럼들, 콜렉션 요소 컬럼이나
+ 컬럼들 그리고 가능하면 인덱스 컬럼들이나 컬럼들을 가진 전용 콜렉션 테이블을 필요로 한다.
+
+
+
+ 값들을 가진 콜렉션의 경우, 우리는 <element> 태그를 사용한다.
+
+
+
+
+
+
+
+
+ ]]>
+
+
+
+ column (옵션): 콜렉션 요소 값들을 소유하는 컬럼의 이름.
+
+
+
+
+ formula (옵션): 요소를 평가하는데 사용되는 SQL formula.
+
+
+
+
+ type (필수): 콜렉션 요소의 타입.
+
+
+
+
+
+
+ many-to-many association 연관은 <many-to-many> 요소를
+ 사용하여 지정된다.
+
+
+
+
+
+
+
+
+
+
+
+
+ ]]>
+
+
+
+ column (옵션): 요소 foreign 키 컬럼의 이름.
+
+
+
+
+ formula (옵션): 요소 foreign 키 값을 평가하는데 사용되는 SQL formula.
+
+
+
+
+ class (필수): 연관된 클래스의 이름.
+
+
+
+
+ fetch (옵션 - 디폴트는 join):
+ 이 연관에 대해 outer-join 페칭 또는 sequential select 페칭을 이용 가능하게 만든다. 이것은 특별한 경우이다;
+ 엔티티 그리고 다른 엔티티들과 그것의 many-to-many 관계들에 대한 (하나의 SELECT
+ 내에서) 전체 eager 페칭의 경우, 당신은 콜렉션 그 자체에 대해서 뿐만 아니라 내포된 요소 <many-to-many>
+ 상의 이 속성에 대해 join 페칭을 이용 가능하게 할 것이다.
+
+
+
+
+ unique (옵션):
+ foreign-key 컬럼에 대한 유일 컨스트레인트의 DDL 생성을 가능하도록 한다. 이것은 연관 다중성
+ (association multiplicity)을 효율적으로 one to many로 만든다.
+
+
+
+
+ not-found (옵션 - 디폴트는 exception):
+ 누락된 행들을 참조하는 foreign 키들이 어떻게 처리될 것인지를 지정한다:
+ ignore는 누락된 한 행을 한 개의 연관으로 다룰 것이다.
+
+
+
+
+ entity-name (옵션): class에 대한 하나의 대안으로서,
+ 연관된 클래스의 엔티티 이름.
+
+
+
+
+
+
+ 몇몇 예제들, 먼저 문자열들을 가진 set:
+
+
+
+
+
+]]>
+
+
+ (order-by 속성에 의해 결정되는 반복 순서를 가진) 정수들을 포함하는 bag :
+
+
+
+
+
+]]>
+
+
+ 엔티티들을 가진 배열 - 이 경우에, many to many 연관 :
+
+
+
+
+
+
+]]>
+
+
+ 날짜들에 대한 문자열 인덱스들을 가진 map :
+
+
+
+
+
+
+]]>
+
+
+ 컴포넌트들의 리스트(다음 장에서 논의됨):
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+
+ One-to-many 연관들
+
+
+ one to many 연관은 중재하는 콜렉션 테이블 없이 foreign 키를 통해 두 개의 클래스들의 테이블들을
+ 연결시킨다. 이 매핑은 통상의 자바 콜렉션들의 어떤 의미를 상실한다:
+
+
+
+
+
+ 포함된 엔티티 클래스의 인스턴스는 그 콜렉션의 하나 이상의 인스턴스에 속하지 않을 수 있다
+
+
+
+
+ 포함된 엔티티 클래스의 인스턴스는 콜렉션 인덱스의 하나 이상의 값에서 나타나지 않을 수 있다
+
+
+
+
+
+ Product로부터 Part로의 연관은 foreign 키 컬럼과 Part
+ 테이블에 대한 인덱스 컬럼의 존재를 필요로 한다. <one-to-many> 태그는 이것이 one to many
+ 연관임을 나타낸다.
+
+
+
+
+
+
+
+
+ ]]>
+
+
+
+ class (필수): 연관된 클래스의 이름.
+
+
+
+
+ not-found (옵션 - 디폴트는 exception):
+ 누락된 행들을 참조하는 캐시된 식별자들이 어떻게 처리될 것인지를 지정한다:
+ ignore는 누락된 한 행을 한 개의 연관으로 다룰 것이다.
+
+
+
+
+ entity-name (옵션): class에 대한 대안으로서,
+ 연관된 클래스의 엔티티 이름.
+
+
+
+
+
+
+ <one-to-many> 요소는 어떤 컬럼들을 선언하는데 필요하지 않음을 주목하라. 어딘가에
+ table 이름을 지정하는 것도 필수적이지 않다.
+
+
+
+ 매우 중요한 노트: 만일 <one-to-many> 연관의 foreign 키 컬럼이
+ NOT NULL로 선언될 경우, 당신은 <key> 매핑을 not-null="true"로
+ 선언해야 하거나 inverse="true"로 마크된 콜렉션 매핑을 가진 양방향 연관을 사용해야 한다.
+ 양방향 연관들에 대한 논의는 이 장의 뒷부분을 보라.
+
+
+
+ 이 예제는 name으로 Part 엔티티들을 가진 map을 보여준다(여기서 partName은
+ Part의 영속 프로퍼티이다). formula-기반 index의 사용을 주목하라.
+
+
+
+
+
+
+]]>
+
+
+
+
+
+ 개선된 콜렉션 매핑들
+
+
+ Sorted 콜렉션들
+
+
+ Hibernate는 java.util.SortedMap과 java.util.SortedSet를 구현하는
+ 콜렉션들을 지원한다. 당신은 매핑 파일 속에 하나의 comparator를 지정해야 한다:
+
+
+
+
+
+
+
+]]>
+
+
+ sort 속성에 허용되는 값들은 unsorted, natural,
+ 그리고 java.util.Comparator를 구현하는 클래스의 이름이다.
+
+
+
+ Sorted 콜렉션들은 java.util.TreeSet 또는 java.util.TreeMap처럼 행동한다.
+
+
+
+ 만일 당신이 데이터베이스 그 자체가 콜렉션 요소들을 순서지우도록(order)원할 경우 set,
+ bag 또는map 매핑들에 대해 order-by 속성을 사용하라.
+ 이 해결책은 JDK 1.4 이상의 버전에서만 이용 가능하다(그것은 LinkedHashSet 또는 LinkedHashMap을
+ 사용하여 구현된다). 이것은 메모리 내가 아닌, SQL 질의 내에서 순서지움(ordering)을 수행한다.
+
+
+
+
+
+
+
+]]>
+
+
+ order-by 속성의 값은 HQL 순서지움(ordering)이 아니라 SQL 순서지움(ordering)임을 노트하라!
+
+
+
+ 연관들은 콜렉션 filter()를 사용하여 실행 시에 어떤 임의의 criteria(기준)을 사용하여 정렬(sort)될
+ 수도 있다.
+
+
+
+
+
+
+
+ 양방향 연관들
+
+
+ 양방향 연관은 연관의 양 "끝(end)들"로부터 네비게이션을 허용한다.
+ 두 가지 종류의 양방향 연관들이 지원된다:
+
+
+
+ one-to-many
+
+
+ 한쪽 끝에 set 또는 bag 값을 갖고, 다른 쪽 긑에 단일 값을 가진 연관
+
+
+
+
+ many-to-many
+
+
+ 양 끝에서 set 또는 bag 값을 가진 연관
+
+
+
+
+
+
+
+
+ 당신은 동일한 두 개의 many-to-many 연관들을 동일한 데이터베이스 테이블로 간단하게 매핑하고 한 쪽 끝을
+ inverse(당신의 선택은 하나이지만, 그것은 인덱싱된 콜렉션일 수 없다)로 선언함으로써 하나의 양방향
+ many-to-many 연관을 지정할 수도 있다.
+
+
+
+ 다음은 양방향 many-to-many 연관에 관한 예제이다; 각각의 카테고리는 많은 아이템들을 가질 수 있고 각각의 아이템은 많은
+ 카테고리들 속에 있을 수 있다:
+
+
+
+
+ ...
+
+
+
+
+
+
+
+
+ ...
+
+
+
+
+
+
+]]>
+
+
+ 연관의 inverse 끝(end)에 대해서만 행해진 변경들은 영속화 되지 않는다. 이것은 Hibernate가
+ 모든 양방향 연관에 대해 메모리 내에 두 개의 표상들을 갖는다는 점을 의미한다: A로부터 B로의 하나의 링크와 B로부터 A로의 또 다른 링크.
+ 만일 당신이 자바 객체 모형에 대해 그리고 자바에서 many-to-many 관계를 생성시키는 방법에 대해 생각하면 이것은 이해하기가 더 쉽다:
+
+
+
+
+
+ non-inverse 측은 메모리 내 표상을 데이터베이스로 저장하는데 사용된다.
+
+
+
+ 당신은 하나의 one-to-many 연관을 하나의 many-to-one 연관으로서 동일한 테이블 컬럼(들)로 매핑하고 many-값을 가진 끝(end)을
+ inverse="true"로 선언함으로써 하나의 양방향 연관을 정의할 수도 있다.
+
+
+
+
+ ....
+
+
+
+
+
+
+
+
+ ....
+
+]]>
+
+
+ 연관의 한쪽 끝을 inverse="true"로 매핑하는 것은 cascade들을 가진 오퍼레이션에 영향을 주지 않으며,
+ 이것들은 orthogonal(직교) 개념들이다!
+
+
+
+
+
+ Ternary associations(세겹 연관들)
+
+
+ 세 겹의 연관을 매핑하는 세 가지 가능한 접근법들이 존재한다. 하나의 접근법은 그것의 인덱스로서 연관관계를 가진
+ Map을 사용하는 것이다:
+
+
+
+
+
+
+]]>
+
+
+
+
+
+]]>
+
+
+ 두 번째 접근법은 그 연관을 엔티티 클래스로서 단순하게 리모델링 하는 것이다. 이것은 우리가 가장 공통적으로 사용하는 접근법이다.
+
+
+
+ 마지막 대안은 우리가 나중에 논의하게 될 composite 요소들을 사용하는 것이다.
+
+
+
+
+
+ <idbag> 사용하기
+
+
+ 만일 당신이 composite 키들이 나쁜 것이고 엔티티들이 합성 식별자들(대용 키들, surrogate keys)을 가져야 한다는
+ 우리의 견해를 전적으로 수용할 경우, 당신은 우리가 지금까지 보여주었던 값들을 가진 콜렉션들과 many to many 연관들이 모두
+ composite 키들을 가진 테이블들로 매핑된다는 약간 이상한 점을 발견할 수도 있다! 이제 이 점은 꽤 논의의 여지가 있다; 순수한
+ 연관 테이블은 (비록 composite 값들을 가진 콜렉션일 수도 있을지라도) 대용 키로부터 많은 이점을
+ 취하지 않는 것처럼 보인다. 그럼에도 불구하고 Hibernate는 당신이 값들을 가진 콜렉션들과 many to many 연관들을 대용 키를 가진
+ 테이블로 매핑시키는 것을 당신에게 허용해주는 특징을 제공한다.
+
+
+
+ <idbag> 요소는 bag 의미를 가진 List(또는 Collection)을
+ 매핑하도록 당신에게 허용해준다.
+
+
+
+
+
+
+
+
+]]>
+
+
+ 당신이 볼 수 있듯이, <idbag>은 마치 엔티티 클래스인양 synthetic id generator(합성 id 생성기)를
+ 갖는다! 다른 대용 키는 각각의 콜렉션 행에 할당된다. 하지만 Hibernate는 특정 행의 대용 키 값을 발견하는 메커니즘을 제공하지 않는다.
+
+
+
+ <idbag>의 업데이트 퍼포먼스는 정규 <bag> 보다 훨씬 좋다는 점을
+ 노트하라! Hibernate는 마치 list, map, 또는 set인양, 개별 행들을 효율적으로 위치지울 수 있고 그것들을 개별적으로 업데이트
+ 하거나 삭제시킬 수 있다.
+
+
+
+ 현재 구현에서, native 식별자 생성 방도는 <idbag> 콜렉션 식별자들에 대해
+ 지원되지 않는다.
+
+
+
+
+
+
+
+
+
+
+
+ 콜렉션 예제들
+
+
+ 앞의 절들은 꽤 혼동스럽다. 따라서 예제를 살펴보자. 다음 클래스:
+
+
+
+
+
+ 는 Child 인스턴스들을 가진 하나의 콜렉션을 갖고 있다. 만일 각각의 자식이 최소한 한 개의 부모를 가질 경우,
+ 대부분의 고유한 매핑은 one-to-many 연관이다:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ 이것은 다음 테이블 정의들로 매핑된다:
+
+
+
+
+
+ 만일 부모가 필수적이라면, 양방향 one-to-many 연관관계를 사용하라:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ NOT NULL 컨스트레인트를 주목하라:
+
+
+
+
+
+ 대안적으로, 만일 당신이 이 연관관계가 단방향이어야 함을 절대적으로 역설할 경우, 당신은 <key>
+ 매핑 상에 NOT NULL 컨스트레인트를 선언할 수 있다:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ 반면에, 만일 자식이 여러 부모들을 가질 수 있을 경우, many-to-many 연관이 적절하다:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ 테이블 정의들:
+
+
+
+
+
+ 부모/자식 관계 매핑을 연습하는 더 많은 예제들과 전체 리허설은 를 보라.
+
+
+
+ 비록 더 많은 신종 연관 매핑들이 가능할지라도, 우리는 다음 장에서 모든 가능성들을 분류할 것이다.
+
+
+
+
+
diff --git a/reference/ko/modules/component_mapping.xml b/reference/ko/modules/component_mapping.xml
new file mode 100644
index 0000000000..9b69641d29
--- /dev/null
+++ b/reference/ko/modules/component_mapping.xml
@@ -0,0 +1,374 @@
+
+ Component 매핑
+
+
+ component의 개념은 Hibernate에서 다른 용도로 몇몇 다른 컨텍스트들 내에서 재사용된다.
+
+
+
+ 종속 객체들
+
+
+ 하나의 컴포넌트는 엔티티 참조가 아닌, value 타입으로서 영속화 되는 하나의 포함된 객체이다. "컴포넌트" 용어는
+ (아키텍처 수준의 컴포넌트들이 아닌) composition(구성,합성)에 대한 객체-지향적인 개념을 언급한다.
+ 예를 들어 당신은 다음과 같이 개인을 모형화 시킬 수도 있다:
+
+
+
+
+
+
+
+ 이제 Name은 Person의 컴포넌트로서 영속화 될 수도 있다. Name이
+ 그것의 영속 프로퍼티들에 대한 getter 메소드와 setter 메소드를 정의하지만, 어떤 인터페이스들이나 식별자 프로퍼티들을 선언하는 것을
+ 필요로 하지 않음을 주목하라.
+
+
+
+ 우리의 Hibernate 매핑은 다음과 같을 것이다:
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ person 테이블은
+ pid,
+ birthday,
+ initial,
+ first,
+ last 컬럼들을 가질 것이다.
+
+
+
+ 모든 값(value) 타입들처럼, 컴포넌트들은 공유된 참조들을 지원하지 않는다. 달리 말해, 두 명의 개인들은 동일한 이름을 가질 수
+ 있지만, 두 개의 person 객체들은 오직 값 만이 "동일한" 두 개의 독립적인 name 객체들을 포함할 것이다. 컴포넌트의 null 값 의미는
+ 특별한 용도를 위한 것이다. 포함된 객체를 다시 로드시킬 때, Hibernate는 모든 컴포넌트 컬럼들이
+ null일 경우에 전체 컴포넌트가 null이라고 가정할 것이다. 이것은 대부분의 용도에 맞을 것이다.
+
+
+
+ 컴포넌트의 프로퍼티들은 임의의 Hibernate 타입일 수 있다(콜렉션들, many-to-one 연관들, 다른 컴포넌트들, 기타).
+ 내포된 컴포넌트들은 신종의 사용례로 간주되지 않을 것이다. Hibernate는 매우 잘 정제된 객체 모형을
+ 지원하도록 고안되어있다.
+
+
+
+ <component> 요소는 컴포넌트 클래스의 프로퍼티를 포함되는 엔티티에 대한 역 참조로서 매핑시키는
+ <parent> 서브요소를 허용한다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+
+ 종속 객체들을 가진 콜렉션들
+
+
+ 컴포넌트들을 가진 콜렉션들이 지원된다(예를 들면 Name 타입을 가진 배열).
+ <element> 태그를 <composite-element> 태그로
+ 대체시켜서 당신의 컴포넌트 콜렉션을 선언하라.
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ 노트: 만일 당신이 composite 요소를 가진 하나의 Set를 정의할 경우, equals()와
+ hashCode()를 정확하게 구현하는 것이 매우 중요하다.
+
+
+
+ Composite 요소들은 컴포넌트들을 포함하지만 콜렉션들을 포함하지 않는다. 만일 당신의 composite 요소 자체가 컴포넌트들을 포함할
+ 경우, <nested-composite-element> 태그를 사용하라. 이것은 꽤 신종의 경우-그것들 자체가
+ 컴포넌트들을 갖고 있는 컴포넌트들의 콜렉션-이다. 이 단계에서 당신은 one-to-many 연관이 더 적절한지를 당신 스스로에게 질문하게
+ 될 것이다. 하나의 엔티티로서 composite 요소를 다시 모델링하려고 시도하라 - 그러나 자바 모형들이 동일할지라도,
+ 관계형 모형과 영속화 의미들은 여전히 약간 다르다.
+
+
+
+ 당신이 하나의 <set>을 사용 중이라면, 하나의 composite 요소 매핑은 null 가능한 프로퍼티들을
+ 지원하지 않음을 노트하길 바란다. Hibernate는 객체들을 삭제할 때 하나의 레코드를 식별하는데 각각의 컬럼들 값을 사용해야 하며
+ (composite 요소 테이블 내에 별도의 프라이머리 키 컬럼이 존재하지 않는다), 그것은 null 값들에 대해서는 불가능하다. 당신은
+ 하나의 composite-요소 내에 not-null 프로퍼티들 만을 사용해야 하거나 하나의 <list>,
+ <map>, <bag> 또는 <idbag>을
+ 선택해야 한다.
+
+
+
+ composite 요소에 대한 하나의 특별한 경우는 내포된 <many-to-one> 요소를 가진 composite 요소이다.
+ 이같은 매핑은 many-to-many 연관 테이블의 특별한 컬럼들을 composite 요소 클래스로 매핑시키는 것을 당신에게 허용해준다. 다음은
+ Order로부터 Item으로의 many-to-many 연관이다. 여기서
+ purchaseDate, price, 그리고 quantity는 연관의
+ 프로퍼티들이다:
+
+
+
+ ....
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ 물론, 양방향 연관 네비게이션의 경우, 다른 측 상에 있는 purchase에 대한 참조가 존재할 수 없다. 컴포넌트들이 값(value) 타입들이고
+ 공유된 참조들을 허용하지 않음을 기억하라. 하나의 Purchase는Order를 가진 set
+ 내에 있을 수 있지만, 그것은 동시에 Item에 의해 참조될 수 없다.
+
+
+ 심지어 세겹의(또는 네 겹의, 기타) 연관들이 가능하다:
+
+
+ ....
+
+
+
+
+
+
+
+]]>
+
+
+ composite 요소들은 다른 엔티티들에 대한 연관들과 동일한 구문을 사용하여 질의들 내에 나타날 수도 있다.
+
+
+
+
+
+ Map 인덱스들로서 컴포넌트들
+
+
+ <composite-map-key> 요소는 당신에게 하나의 컴포넌트 클래스를 하나의 Map의
+ 키로서 매핑시키도록 한다. 당신은 컴포넌트 클래스 상에서 hashCode()와 equals()를
+ 정확하게 오버라이드 시키도록 하라.
+
+
+
+
+ composite 식별자들로서 컴포넌트들
+
+
+ 당신은 하나의 컴포넌트를 하나의 엔티티 클래스에 대한 하나의 식별자로서 사용할 수도 있다. 당신의 컴포넌트 클래스는 어떤 사양들을
+ 충족시켜야 한다:
+
+
+
+
+
+ 그것은 java.io.Serializable을 구현해야 한다.
+
+
+
+
+ 그것은 composite 키 등가(equality)에 대한 데이터베이스 개념과 일치되게, equals()와
+ hashCode()를 다시 구현해야 한다.
+
+
+
+
+
+ 노트: Hibernate3에서, 두 번째 사양은 Hibernate의 절대적으로 엄격한 사양이 아니다.
+ 그러나 아무튼 그것을 행하라.
+
+
+
+ 당신은 compsite 키들을 생성시키는데 IdentifierGenerator를 사용할 수 없다. 대신에 어플리케이션은
+ 그것 자신의 식별자들을 할당해야 한다.
+
+
+
+ 통상의 <id> 선언 위치에 (내포된 <key-property> 요소들을 가진)
+ <composite-id> 태그를 사용하라. 예를 들어, OrderLine 클래스는
+ Order의 (composite) 프라이머리 키에 의존하는 프라이머리 키를 갖는다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ....
+
+]]>
+
+
+ 이제 OrderLine 테이블을 참조하는 임의의 foreign 키들이 또한 compsite이다. 당신은 다른 클래스들에 대한
+ 당신의 매핑들 속에 이것을 선언해야 한다. OrderLine에 대한 하나의 연관은 다음과 같이 매핑될 것이다:
+
+
+
+
+
+
+
+]]>
+
+
+ (<column> 태그가 모든 곳에서 column 속성에 대한 대안임을 노트하라.)
+
+
+
+ OrderLine에 대한 many-to-many 연관은 또한 composite foreign 키를 사용한다:
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ Order에서 OrderLine들의 콜렉션이 사용될 것이다:
+
+
+
+
+
+
+
+
+]]>
+
+
+ (통상적으로 <one-to-many> 요소는 컬럼들을 선언하지 않는다.)
+
+
+
+ 만일 OrderLine 자체가 하나의 콜렉션을 소유할 경우, 그것은 또한 하나의 composite foreign 키를 갖는다.
+
+
+
+ ....
+ ....
+
+
+
+
+
+
+
+
+ ...
+
+
+]]>
+
+
+
+
+ 동적인 컴포넌트들
+
+
+ 당신은 Map 타입의 프로퍼티를 매핑시킬 수도 있다:
+
+
+
+
+
+
+]]>
+
+
+ <dynamic-component> 매핑의 의미는 <component>와 동일하다.
+ 이런 종류의 매핑의 장점은 배치 시에 단지 매핑 문서를 편집함으로써 그 bean의 실제 프로퍼티들을 결정하는 가용성이다. 매핑 문서에
+ 대한 런타임 처리는 또한 DOM 파서를 사용하여 가능하다. 더 좋게는 당신이 Configuration 객체를 통해
+ Hibernate의 구성-시 메타모형에 접근할 수 있다(그리고 변경시킬 수 있다)
+
+
+
+
+
diff --git a/reference/ko/modules/configuration.xml b/reference/ko/modules/configuration.xml
new file mode 100644
index 0000000000..67ef81c76f
--- /dev/null
+++ b/reference/ko/modules/configuration.xml
@@ -0,0 +1,1595 @@
+
+
+ 구성
+
+
+ Hibernate가 많은 다른 환경들에서 동작하도록 설계되어 있으므로, 많은 개수의 구성 파라미터들이 존재한다. 다행히 대부분은 유의미한
+ 디폴트 값들이고 Hibernate는 다양한 옵션들을 보여주는 etc/ 내의 예제 파일 hibernate.properties로
+ 배포된다. 당신은 단지 당신의 classpath 경로 속에 그 파일을 집어넣고 그것을 커스트마이징하기만 해야 한다.
+
+
+
+ 프로그램 상의 구성
+
+
+ org.hibernate.cfg.Configuration의 인스턴스는 어플리케이션의 Java 타입들을 SQL 데이터베이스
+ 타입으로의 전체 매핑 집합을 표현한다. Configuration은 (불변의) SessionFactory를
+ 빌드하는데 사용된다. 매핑들은 여러 XML 매핑 파일들로부터 컴파일 된다.
+
+
+
+ 당신은 Configuration 인스턴스를 초기화 시키고 XML 매핑 문서들을 지정함으로써 Configuration
+ 인스턴스를 얻을 수 있다. 만일 매핑 파일들이 classpath 내에 있다면, addResource()를 사용하라:
+
+
+
+
+
+ (때때로 더 나은) 다른 방법은 매핑된 클래스를 지정하는 것이고, Hibernate로 하여금 당신을 위해 매핑 문서를 찾도록 하라:
+
+
+
+
+
+ 그때 Hibernate는 classpath 내에서 /org/hibernate/auction/Item.hbm.xml과
+ /org/hibernate/auction/Bid.hbm.xml로 명명된 매핑 파일들을 룩업할 것이다. 이 접근법은
+ 임의의 하드코딩된 파일 이름들을 제거한다.
+
+
+
+ Configuration은 또한 구성 프로퍼티들을 지정하는 것을 허용해준다:
+
+
+
+
+
+ 이것은 컨피그레이션 프로퍼티들을 Hibernate에 전달하는 유일한 방법이 아니다. 여러 가지 옵션들은 다음을 포함한다:
+
+
+
+
+
+ java.util.Properties의 인스턴스를 Configuration.setProperties()에
+ 전달한다 .
+
+
+
+
+ classpath의 루트 디렉토리에 hibernate.properties를 위치지운다.
+
+
+
+
+ java -Dproperty=value를 사용하여 System 프로퍼티들을 설정한다.
+
+
+
+
+ hibernate.cfg.xml에 <property> 요소들을 포함한다
+ (나중에 논의됨).
+
+
+
+
+
+ 당신이 빠르게 시작하고 원할 경우 hibernate.properties는 가장 쉬운 접근법이다.
+
+
+
+ Configuration은 시작 시(startup-time) 객체로서 일단 SessionFactory가
+ 생성되면 폐기되게끔 예정되어 있다.
+
+
+
+
+
+ SessionFactory 얻기
+
+
+ 모든 매핑들이 Configuration에 의해 파싱되었을 때, 어플리케이션은 Session
+ 인스턴스들에 대한 팩토리를 얻어야 한다. 이 팩토리는 모든 어플리케이션 쓰레드들에 의해 공유되도록 고안되었다:
+
+
+
+
+
+ 하지만 Hibernate는 당신의 어플리케이션이 하나 이상의 SessionFactory를 초기화 시키는 것을 허용한다.
+ 이것은 당신이 하나 이상의 데이터베이스를 사용하는 경우에 유용하다.
+
+
+
+
+
+ JDBC 커넥션들
+
+
+ 대개 당신은 SessionFactory로 하여금 당신을 위한 JDBC 커넥션들을 생성시키고 풀링시키는 것을 원한다.
+ 만일 당신이 이 접근법을 취할 경우, 한 개의 Session을 여는 것은 다음과 같이 간단하다:
+
+
+
+
+
+ 당신이 데이터베이스에 대한 접근을 요청하는 어떤 것을 행하자 마자, 한 개의 JDBC 커넥션이 그 풀로부터 얻어질 것이다.
+
+
+
+ 이것이 동작하도록 하기 위해서, 우리는 몇몇 JDBC 커넥션 프로퍼티들을 Hibernate에 전달할 필요가 있다. 모든 Hibernate 프로퍼티
+ 이름들과 의미론들은 org.hibernate.cfg.Environment 클래스 상에 정의되어 있다. 우리는 이제 JDBC
+ 커넥션 구성을 위한 가장 중요한 설정들을 설명할 것이다.
+
+
+
+ 만일 당신이 다음 프로퍼티들을 설정할 경우 Hibernate는 java.sql.DriverManager를 사용하여 커넥션들을
+ 얻을 것이다(그리고 풀링시킬 것이다):
+
+
+
+
+
+ 하지만 Hibernate 자신의 커넥션 풀링 알고리즘은 아주 기본적이다. 그것은 당신이 시작하는 것을 도와주려고 의도되었고 제품
+ 시스템 용도 또는 퍼포먼스 테스트용으로는 고안되지 않았다. 최상의 퍼포먼스와 안정성을 위해서는 제 3의 풀을 사용하라. 즉
+ hibernate.connection.pool_size 프로퍼티를 커넥션 풀 지정 설정들로 대체하라. 이것은 Hibernate의 내부
+ pool을 오프시킬 것이다. 예를 들어 당신은 C3P0를 사용할 수도 있다.
+
+
+
+ C3P0는 lib 디펙토리 속에 Hibernate에 배포된 오픈 소스 JDBC 커넥션 풀이다. 당신이 hibernate.c3p0.*
+ 프로퍼티들을 설정할 경우 Hibernate는 커넥션 풀링을 위해 그것의 C3P0ConnectionProvider를 사용할 것이다.
+ 만일 당신이 Proxool을 사용하고자 원할 경우 패키지화 된 hibernate.properties를 참조하고 추가 정보는
+ Hibernate 웹 사이트를 참조하라.
+
+
+
+ 다음은 C3P0에 대한 사용하는 예제 hibernate.properties 파일이다:
+
+
+
+
+
+ 어플리케이션 서버 내부의 용도로, 당신은 JNDI로 등록된 어플리케이션 서버 Datasource로부터 커넥션을 얻기
+ 위해 항상 Hibernate를 구성해야 한다. 당신은 적어도 다음 프로퍼티들 중 하나를 최소한으로 설정할 필요가 있을 것이다.
+
+
+
+
+
+ 다음은 어플리케이션 서버 제공 JNDI 데이터소스용 예제 hibernate.properties 파일이다:
+
+
+
+
+
+ JNDI datasource로부터 얻어진 JDBC 커넥션들은 어플리케이션 서버의 컨테이너에 의해 관리되는 트랜잭션들에 자동적으로 참여할 것이다.
+
+
+
+ 임의의 커넥션 프로퍼티들은 프로퍼티 이름 앞에 "hibernate.connnection"을 첨가하여 부여될 수 있다. 예를 들어
+ 당신은 hibernate.connection.charSet을 사용하여 charSet을 지정할 수도 있다.
+
+
+
+ 당신은 org.hibernate.connection.ConnectionProvider 인터페이스를 구현함으로써 JDBC 커넥션들을
+ 얻는 당신 자신의 플러그인 방도를 정의할수도 있다. 당신은 hibernate.connection.provider_class를
+ 설정하여 맞춤형 구현을 선택할 수도 있다.
+
+
+
+
+
+ 선택적인 구성 프로퍼티들
+
+
+ 실행 시에 Hibernate의 행위를 제어하는 많은 다른 프로퍼티들이 존재한다. 모든 것이 옵션이지만 합당한 디폴트 값들을 갖는다.
+
+
+
+ 경고: 이들 프로퍼티들 중 몇몇은 "system-level" 전용이다. 시스템 레벨 프로퍼티들은 오직
+ java -Dproperty=value 또는 hibernate.properties를 통해서만 설정될 수
+ 있다. 그것들은 위에 설명된 다른 기법들에 의해 설정될 수 없다.
+
+
+
+ Hibernate 구성 프로퍼티들
+
+
+
+
+
+ 프로퍼티 이름
+ 용도
+
+
+
+
+
+ hibernate.dialect
+
+
+ 특정 관계형 데이터베이스에 최적화 된 SQL을 생성시키는 것을 Hibernate에게 허용해주는
+ Hibernate Dialect의 클래스명.
+
+ 예.
+ full.classname.of.Dialect
+
+
+
+
+
+ hibernate.show_sql
+
+
+ 모든 SQL 문장들을 콘솔에 기록한다.
+
+ 예.
+ true | false
+
+
+
+
+
+ hibernate.default_schema
+
+
+ 생성된 SQL 내에 주어진 schema/tablespace로서 수식이 없는 테이블이름들을 수식한다.
+
+ 예.
+ SCHEMA_NAME
+
+
+
+
+
+ hibernate.default_catalog
+
+
+ 주어진 SQL 내에 주어진 카타록으로서 수식이 없는 테이블이름들을 수식한다.
+
+ 예.
+ CATALOG_NAME
+
+
+
+
+
+ hibernate.session_factory_name
+
+
+ SessionFactory는 그것이 생성된 후에 JNDI 내에서 이 이름에 자동적으로 바인드
+ 될 것이다.
+
+ 예.
+ jndi/composite/name
+
+
+
+
+
+ hibernate.max_fetch_depth
+
+
+ single-ended 연관관계들(one-to-one, many-to-one)의 경우에 outer join fetch 트리의 최대 "깊이"를
+ 설정한다. 0은 디폴트 outer join fetching을 사용불가능하게 만든다.
+
+ 예.
+ 0과
+ 3 사이의 값들이권장된다
+
+
+
+
+
+ hibernate.default_batch_fetch_size
+
+
+ 연관들의 Hibernate 배치 페칭에 대한 디폴트 크기를 설정한다.
+
+ 예.
+ 권장되는 값들은 4, 8,
+ 16
+
+
+
+
+
+ hibernate.default_entity_mode
+
+
+ 이 SessionFactory로부터 열려진 모든 세션들에 대해 엔티티 표현을 디폴트 모드로
+ 설정한다
+
+ dynamic-map, dom4j,
+ pojo
+
+
+
+
+
+ hibernate.order_updates
+
+
+ 업데이트 중인 항목들의 프라이머리 키 값에 의해 SQL 업데이트들이 순서(ordering) 지워지도록 Hibernate에게
+ 강제시킨다. 이것은 고도의 동시성 시스템들에서 더 적은 트랜잭션 데드락(deadlock)들로 귀결될 것이다
+
+ 예.
+ true | false
+
+
+
+
+
+ hibernate.generate_statistics
+
+
+ 이용 가능하게 되면, Hibernate는 퍼포먼스 튜닝에 유용한 통계들을 수집할 것이다.
+
+ 예.
+ true | false
+
+
+
+
+
+ hibernate.use_identifer_rollback
+
+
+ 이용 가능하게 되면, 객체가 삭제될 때 생성된 식별자 프로퍼티들은 디폴트 값들로 재설정될 것이다.
+
+ 예.
+ true | false
+
+
+
+
+
+ hibernate.use_sql_comments
+
+
+ 이용 가능하게 되면, Hibernate는 보다 쉬운 디버깅을 위해 SQL 내에 주석들을 생성시킬 것이다.
+ 디폴트는 false.
+
+ 예.
+ true | false
+
+
+
+
+
+
+
+
+ Hibernate JDBC 및 커넥션 프로퍼티들
+
+
+
+
+
+ 프로퍼티 이름
+ 용도
+
+
+
+
+
+ hibernate.jdbc.fetch_size
+
+
+ 0 아닌 값은 JDBC fetch 사이즈를 결정한다(Statement.setFetchSize()을 호출한다 ).
+
+
+
+
+ hibernate.jdbc.batch_size
+
+
+ 0 아닌 값은 Hibernate에 의한 JDBC2 배치 업데이트의 사용을 이용 가능하게 한다.
+
+ 예.
+ 5와 30 사이의 값들이 권장된다
+
+
+
+
+
+ hibernate.jdbc.batch_versioned_data
+
+
+ 당신의 JDBC 드라이버가 executeBatch()로부터 정확한 행 카운트들을 반환할 경우에
+ 이 프로퍼티를 true로 설정하라(대개 이 옵션을 사용 가능하게 하는 것이 안전하다).
+ 그러면 Hibernate는 자동적으로 버전화 된 데이터에 대해 배치화된(batched) DML을 사용할 것이다.
+ 디폴트는 false.
+
+ 예.
+ true | false
+
+
+
+
+
+ hibernate.jdbc.factory_class
+
+
+ 맞춤형 Batcher를 선택한다. 대부분의 어플리케이션들은 이 구성 프로퍼티를 필요로 하지
+ 않을 것이다.
+
+ 예.
+ classname.of.Batcher
+
+
+
+
+
+ hibernate.jdbc.use_scrollable_resultset
+
+
+ Hibernate에 의한 JDBC2 스크롤 가능한 결과셋들의 사용을 가능하게 해준다. 이 프로퍼티는 사용자가 제공한
+ JDBC커넥션들을 사용할 때에만 필수적이고, 그 밖의 경우 Hibernate는 커넥션 메타데이터를 사용한다.
+
+ 예.
+ true | false
+
+
+
+
+
+ hibernate.jdbc.use_streams_for_binary
+
+
+ binary 또는 serializable 타입들을 JDBC로 기록하고
+ /JDBC로부터 binary 또는 serializable 타입들을 읽어들일 때
+ 스트림들을 사용한다(시스템-레벨 프로퍼티).
+
+ 예.
+ true | false
+
+
+
+
+
+ hibernate.jdbc.use_get_generated_keys
+
+
+ insert 후에 고유하게 생성된 키들을 검색하는데 JDBC3 PreparedStatement.getGeneratedKeys()의
+ 사용을 이용 가능하도록 만든다. JDBC3+ 드라이버와 JRE1.4+를 필요로 하고, 당신의 드라이버가 Hibernate
+ 식별자 생성자들에 문제가 있을 경우에 false로 설정하라. 디폴트로 커넥션 메타 데이터를 사용하여 드라이버
+ 가용성들을 결정하려고 시도하라.
+
+ 예.
+ true|false
+
+
+
+
+
+ hibernate.connection.provider_class
+
+
+ Hibernate에 JDBC 커넥션들을 제공하는 맞춤형 ConnectionProvider의 클래스명.
+
+ 예.
+ classname.of.ConnectionProvider
+
+
+
+
+
+ hibernate.connection.isolation
+
+
+ JDBC transaction isolation 레벨을 설정한다. 의미있는 값들로 java.sql.Connection을
+ 체크하지만 대부분의 데이터베이스들이 모든 격리(isolate) 레벨들을 지원하지 않음을 노트하라.
+
+ 예.
+ 1, 2, 4, 8
+
+
+
+
+
+ hibernate.connection.autocommit
+
+
+ JDBC 풀링된 커넥션들에 대해 자동커밋을 이용 가능하도록 한다(권장되지 않음).
+
+ 예.
+ true | false
+
+
+
+
+
+ hibernate.connection.release_mode
+
+
+ Hibernate가 JDBC 커넥션들을 해제하게 될 시점을 지정한다. 디폴트로 한 개의 JDBC 커넥션은 그 세션이 명시적으로
+ 닫히거나 연결해제되기 전까지 보관된다. 어플리케이션 트랜잭션 서버 JTA 데이터소스의 경우, 당신은 모든 JDBC
+ 호출 후에 커넥션들을 과감하게 해제시키기 위해 after_statement를 사용해야 한다. 비-JTA
+ 연결의 경우, after_transaction을 사용하여 각각의 트랜잭션의 끝에서 커넥션들을
+ 해제시키는 것이 종종 의미가 있다. auto는 JTA 및 CMT 트랜잭션 방도들의 경우에
+ after_statement를 선택하고 JDBC 트랜잭션 방도에 대해 after_transaction를
+ 선택할 것이다.
+
+ eg.
+ on_close (디폴트) | after_transaction |
+ after_statement | auto
+
+
+
+
+
+ hibernate.connection.<propertyName>
+
+
+ JDBC 프로퍼티 propertyName을 DriverManager.getConnection()에
+ 전달한다.
+
+
+
+
+ hibernate.jndi.<propertyName>
+
+
+ propertyName 프로퍼티를 JNDI InitialContextFactory에 전달한다.
+
+
+
+
+
+
+
+ Hibernate Cache 프로퍼티들
+
+
+
+
+
+ 프로퍼티 이름
+ 용도
+
+
+
+
+
+ hibernate.cache.provider_class
+
+
+ 맞춤형 CacheProvider의 클래스명.
+
+ 예.
+ classname.of.CacheProvider
+
+
+
+
+
+ hibernate.cache.use_minimal_puts
+
+
+ 읽기가 매우 빈번한 경우에, 쓰기를 최소화 시키기 위해 second-level 캐시 연산을 최적화 시킨다. 이 설정은 Hibernate3에서 클러스터링 된
+ 캐시들에 가장 유용하고, Hibernate3에서는 클러스터링된 캐시 구현들에 대해 디폴트로 이용 가능하다.
+
+ 예.
+ true|false
+
+
+
+
+
+ hibernate.cache.use_query_cache
+
+
+ 질의 캐시를 가능하게 만든다. 개별 질의들은 여전히 캐시 가능한 것으로 설정되어야 한다.
+
+ 예.
+ true|false
+
+
+
+
+
+ hibernate.cache.use_second_level_cache
+
+
+ second-level 캐시를 완전히 사용 불가능하게 하는데 사용될 수 있고, 그것은 <cache> 매핑을
+ 지정하는 클래스들에 대해 디폴트로 이용 가능이다.
+
+ 예.
+ true|false
+
+
+
+
+
+ hibernate.cache.query_cache_factory
+
+
+ 맞춤형 QueryCache 인터페이스의 클래스명. 디폴트는 미리 빌드된
+ StandardQueryCache.
+
+ 예.
+ classname.of.QueryCache
+
+
+
+
+
+ hibernate.cache.region_prefix
+
+
+ second-level 캐시 영역 이름들에 사용할 접두어.
+
+ 예.
+ prefix
+
+
+
+
+
+ hibernate.cache.use_structured_entries
+
+
+ 인간에게 보다 더 친숙한 형식으로 second-level 캐시 속에 데이터를 저장하도록 Hibernate에게 강제시킨다..
+
+ 예.
+ true|false
+
+
+
+
+
+
+
+
+ Hibernate 트랜잭션 프로퍼티들
+
+
+
+
+
+ 프로퍼티 이름
+ 용도
+
+
+
+
+
+ hibernate.transaction.factory_class
+
+
+ Hibernate Transaction API 에 사용할 TransactionFactory의
+ 클래스 이름.(디폴트는 JDBCTransactionFactory).
+
+ 예.
+ classname.of.TransactionFactory
+
+
+
+
+
+ jta.UserTransaction
+
+
+ 어플리케이션 서버로부터 JTA UserTransaction을 얻기 위해 JTATransactionFactory에
+ 의해 사용되는 JNDI 이름.
+
+ 예.
+ jndi/composite/name
+
+
+
+
+
+ hibernate.transaction.manager_lookup_class
+
+
+ TransactionManagerLookup의 클래스명- JVM 레벨의 캐싱이 이용 가능할 때 또는 JTA 환경에서
+ hilo generator를 사용할 때 필요하다.
+
+ 예.
+ classname.of.TransactionManagerLookup
+
+
+
+
+
+ hibernate.transaction.flush_before_completion
+
+
+ 만일 사용가능토록 하면, 트랜잭션의 before completion 단계 동안에 세션이 자동적으로 flush 될 것이다.
+ (CMT에 대해 Hibernate를 사용할 때 매우 유용하다.)
+
+ 예.
+ true | false
+
+
+
+
+
+ hibernate.transaction.auto_close_session
+
+
+ 만일 사용가능토록 하면, after completion 단계 동안에 세션이 자동적으로 닫혀질 것이다.
+ (CMT에 대해 Hibernate를 사용할 때 매우 유용하다.)
+
+ 예.
+ true | false
+
+
+
+
+
+
+
+
+ 여러가지 프로퍼티들
+
+
+
+
+
+ 프로퍼티 이름
+ 용도
+
+
+
+
+
+ hibernate.query.factory_class
+
+
+ Chooses the HQL 파서 구현을 선택한다.
+
+ 예.
+ org.hibernate.hql.ast.ASTQueryTranslatorFactory 또는
+ org.hibernate.hql.classic.ClassicQueryTranslatorFactory
+
+
+
+
+
+ hibernate.query.substitutions
+
+
+ Hibernate 질의들 내의 토큰들로부터 SQL 토큰들로의 매핑(예를 들어 토큰들은 함수 이름 또는 리터럴 이름일 수 있다).
+
+ 예.
+ hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC
+
+
+
+
+
+ hibernate.hbm2ddl.auto
+
+
+ SessionFactory가 생성될 때 스키마 DDL을 데이터베이스로 자동적으로 내보낸다. create-drop의 경우,
+ SessionFactory가 명시적으로 닫혀질 때,, 데이터베이스 스키마가 드롭될 것이다.
+
+ 예.
+ update | create | create-drop
+
+
+
+
+
+ hibernate.cglib.use_reflection_optimizer
+
+
+ 런타임 reflection 대신에 CGLIB의 사용을 가능하도록 만든다(시스템 레벨 프로퍼티). Reflection은 문제가 발생할 시에 때때로 유용할 수 있고,
+ 당신이 optimizer를 사용하지 않을 경우조차도 Hibernate는 항상 필요로 함을 유의하라. 당신은 hibernate.cfg.xml
+ 속에 이 프로퍼티를 설정할수 없다.
+
+ 예.
+ true | false
+
+
+
+
+
+
+
+
+ SQL Dialects
+
+
+ 당신은 항상 당신의 데이터베이스를 위해 hibernate.dialect 프로퍼티를 정확한 org.hibernate.dialect.Dialect
+ 서브클래스로 설정해야 한다. 만일 당신이 dialect를 지정할 경우, 당신이 프로퍼티들을 수작업으로 지정하는 노력을 절약하도록 Hibernate는 위에 열거된 다른 프로퍼티들
+ 중 몇몇에 대해 의미있는 디폴트들을 사용할 것이다.
+
+
+
+
+
+
+
+ Outer Join Fetching
+
+
+ 만일 당신의 데이터베이스가 ANSI, Oracle, 또는 Sybase 스타일의 outer join들을 지원할 경우, outer join
+ fetching은 (데이터베이스 그 자체에 의해 보다 더 많은 작업이 수행되는 비용으로) 데이터베이스로의 그리고
+ 데이터베이스로부터의 라운드 트립들의 개수를 제한함으로써 종종 퍼포먼스를 증가시킬 것이다. Outer join fetching은
+ many-to-one, one-to-many, many-to-many,one-to-one 연관관계들이 에 의해 연결된 객체들의 전체 그래프가
+ 하나의 SQL SELECT 속에서 검색되게끔 허용해준다.
+
+
+
+ Outer join fetching은 hibernate.max_fetch_depth 프로퍼티를 0으로 설정함으로써
+ 전역적으로 사용 불가능하게 할 수 있다. 1 이상의 값을 설정하는
+ 것은 fetch="join"으로 매핑되었던 모든 one-to-one 및 many-to-one 연관관계들에 대해
+ outer join fetching을 사용 가능하도록 만든다.
+
+
+
+ 추가 정보는 를 보라.
+
+
+
+
+
+ Binary Streams
+
+
+ Oracle은 JDBC 드라이버 로/부터 전달되는 byte 배열들의 크기를 제한시킨다. 만일 당신이
+ binary 또는 serializable 타입의 대형 인스턴스를 사용하고자
+ 원할 경우에, 당신은 hibernate.jdbc.use_streams_for_binary를 사용 가능하게 해야
+ 할 것이다. 이것은 오직 시스템 레벨 설정이다.
+
+
+
+
+
+ Second-level 캐시와 query 캐시
+
+
+ hibernate.cache 접두어가 붙은 프로퍼티들은 Hibernate에 대해 프로세스 또는
+ 클러스터 범위의 두 번째 레벨 캐시 시스템을 사용하는 것을 허용해준다. 상세한 것은
+ 를 보라.
+
+
+
+
+
+ Query Language 치환
+
+
+ 당신은 hibernate.query.substitutions을 사용하여 새로운 Hibernate 질의 토큰들을
+ 정의할 수 있다. 예를 들어:
+
+
+ hibernate.query.substitutions true=1, false=0
+
+
+ 은true와 false 토큰들이 생성된 SQL 내에서
+ 정수 리터럴들로 번역되도록 강제할 것이다.
+
+
+ hibernate.query.substitutions toLowercase=LOWER
+
+
+ 은 SQL LOWER function 함수 이름을 변경하는 것을 당신에게 허용해 줄 것이다
+
+
+
+
+
+ Hibernate 통계
+
+
+ 만일 당신이 hibernate.generate_statistics를 사용 가능하도록 할 경우, Hibernate는
+ SessionFactory.getStatistics()를 통해 가동 중인 시스템을 튜닝할 때 유용한 많은 통계들을
+ 노출시킬 것이다. Hibernate는 심지어 JMX를 통해 이들 통계들을 노출시키도록 구성될 수 있다. 추가 정보는
+ org.hibernate.stats에 있는 인터페이스들에 관한 Javadoc를 읽어라.
+
+
+
+
+
+
+ 로깅
+
+
+ Hibernate는 Apache commons-logging를 사용하여 다양한 이벤트들을 로그시킨다.
+
+
+
+ commons-logging 서비스는 (만일 당신이 classpath 내에 log4j.jar를 포함할 경우) Apache Log4j로
+ 또는 (JDK1.4 이상의 버전에서 실행될 경우) JDK 1.4 로깅으로 직접 출력할 것이다. 당신은 http://jakarta.apache.org에서
+ Log4j를 다운로드 할 수 있다. Log4j를 사용하기 위해, 당신은 log4j.properties 파일을 당신의 classpath
+ 내에 위치지울 필요가 있을 것이고, 예제 properties 파일은 Hibernate의 src/ 디렉토리 내에 배포되어 있다.
+
+
+
+ 우리는 당신이 Hibernate의 로그 메시지들에 익숙해지기를 강력히 권장한다. 읽기 불가능하지 않게끔 가능한 한 상세하게 Hibernate 로그를
+ 만들도록 많은 작업이 행해졌다. 그것은 본질적인 문제던지기 장치이다. 가장 흥미로운 로그 카테고리들이 다음에 있다:
+
+
+
+ Hibernate 로그 카테고리들
+
+
+
+
+
+ 카테고리
+ 기능
+
+
+
+
+ org.hibernate.SQL
+ SQL DML 문장들이 실행될 때 그것들 모두를 로그 시킨다
+
+
+ org.hibernate.type
+ 모든 JDBC 파라미터들을 로그시킨다
+
+
+ org.hibernate.tool.hbm2ddl
+ SQL DDL 문장들이 실행될 때 그것들 모두를 로그 시킨다
+
+
+ org.hibernate.pretty
+
+ flush 시점에서 세션과 연관된 모든 엔티티들(최대 20개의 엔티티들)의 상태를 로그 시킨다
+
+
+
+ org.hibernate.cache
+ 모든 second-level 캐시 액티비티를 로그시킨다
+
+
+ org.hibernate.transaction
+ 트랜잭션 관련 액티비티를 로그 시킨다
+
+
+ org.hibernate.jdbc
+ 모든 JDBC 리소스 취득을 로그 시킨다
+
+
+ org.hibernate.hql.ast.AST
+
+ 질의 파싱 동안에 HQL AST와 SQL AST를 로그시킨다
+
+
+
+ org.hibernate.secure
+ 모든 JAAS 허가 요청들을 로그시킨다
+
+
+ org.hibernate
+
+ 모든 것을 로그시킨다(많은 정보이지만, 문제해결에 매우 유용하다)
+
+
+
+
+
+
+
+ Hibernate로 어플리케이션들을 개발할 때, 당신은 거의 항상 org.hibernate.SQL 카테고리에 대해
+ 이용 가능한 debug 모드로 작업하거나, 다른 방법으로 hibernate.show_sql
+ 프로퍼티를 이용가능하게 하여 작업해야 할 것이다.
+
+
+
+
+
+
+ NamingStrategy 구현하기
+
+
+ org.hibernate.cfg.NamingStrategy 인터페이스는 데이터베이스 객체들과 스키마 요소들에 대한
+ "네이밍 표준"을 지정하는 것을 당신에게 허용해준다.
+
+
+
+ 당신은 Java 식별자들로부터 데이터베이스 식별자들을 자동적으로 생성시키거나 매핑 파일에 주어진 "논리적" 컬럼과 테이블
+ 이름들을 "물리적" 테이블과 컬럼 이름들로 자동적으로 처리하는 규칙들을 제공할 수 있다. 이 특징은 반복되는 잡음(예를 들어
+ TBL_접두어들)을 제거함으로써, 매핑 문서의 말많은 장황함을 감소시키도록 도와준다. Hibernate에
+ 의해 사용되는 디폴트 방도는 아주 작은 작품이다.
+
+
+
+ 당신은 매핑들을 추가하기 이전에 Configuration.setNamingStrategy()를 호출함으로써 다른 방도를
+ 지정할 수 있다:
+
+
+
+
+
+ org.hibernate.cfg.ImprovedNamingStrategy는 어떤 어플리케이션들에 대한 유용한 시작점일 수 있는
+ 미리 빌드된 방도이다.
+
+
+
+
+
+ XML 구성 파일
+
+
+ 구성에 대한 다른 접근법은 hibernate.cfg.xml로 명명된 파일 속에 전체 구성을 지정하는 것이다. 이 파일은
+ hibernate.properties 파일에 대한 대용물로서 사용될 수 있거나, 만일 둘 다 존재할 경우에 프로퍼티들을
+ 중복정의하는데 사용될 수 있다.
+
+
+
+ XML 구성 파일은 디폴트로 당신의 CLASSPATH의 루트에 존재하는 것이 기대된다. 다음은 예제이다:
+
+
+
+
+
+
+
+
+
+
+
+ java:/comp/env/jdbc/MyDB
+ org.hibernate.dialect.MySQLDialect
+ false
+
+ org.hibernate.transaction.JTATransactionFactory
+
+ java:comp/UserTransaction
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ 당신이 볼 수 있듯이, 이 접근법의 장점은 구성에 대한 매핑 파일 이름들을 구체화 시키는 것이다. hibernate.cfg.xml은
+ 또한 당신이 Hibernate 캐시를 튜닝해야할 때 보다 편리하다. hibernate.properties 또는
+ hibernate.cfg.xml 중 어느 것을 사용하는가는 당신의 선택이다. XML 구문을 사용하는 위에 언급된
+ 이점들을 제외하면 둘다 같은 것임을 노트하라.
+
+
+
+ Hibernate 구성으로, Hibernate를 시작하는 것은 다음과 같이 간단하다
+
+
+
+
+
+ 당신은 다음을 사용하여 다른 XML 구성 파일을 찾아낼 수 있다
+
+
+
+
+
+
+
+ J2EE 어플리케이션 서버 통합
+
+
+ Hibernate는 J2EE 인프라스트럭처에 대한 다음 통합 점들을 갖고 있다:
+
+
+
+
+
+ Container-managed datasources: Hibernate는 컨테이너에 의해 관리되는 JDBC 커넥션들을
+ 사용할 수 있고 JNDI를 통해 제공된다. 대개 JTA 호환 TransactionManager와 ResourceManager는
+ 트랜잭션 관리(CMT), 특히 몇몇 데이터소스들을 가로질러 분산된 트랜잭션 핸들링을 처리한다. 물론 당신은 또한 프로그램 상으로
+ 트랜잭션 경계들을 한정할 수도 있거나(BMT) 당신은 당신의 코드가 이식성을 유지하도록 이것에 대한 선택적인 Hibernate
+ Transaction API를 사용하고자 원할 수도 있다.
+
+
+
+
+
+
+
+ 자동적인 JNDI 바인딩: Hibernate는 시작 후에 그것의 SessionFactory를
+ JNDI에 바인드 시킬 수 있다.
+
+
+
+
+
+
+
+ JTA Session 바인딩: Hibernate Session은 당신이 EJB들을 사용하고자
+ 원할 경우에 JTA 트랜잭션들의 영역(scope)에 자동적으로 바인드 시킬 수도 있다. 간단하게 JNDI로부터 SessionFactory를
+ 룩업하고 현재 Session을 얻어라. Hibernate로 하여금 당신의 JTA 트랜잭션이 완료될 때 Session을
+ flush시키고 닫는 것을 처리하도록 하라. 트랜잭션 경계 설정은 EJB 배치 디스크립터들 내에서 선언적이다.
+
+
+
+
+
+
+
+ JMX 배치: 만일 당신이 JMX 가용성이 있는 어플리케이션 서버(예를 들면 JBoss AS)를 갖고 있다면,
+ 당신은 Hibernate를 하나의 managed MBean으로서 배치하는 것을 선택할 수 있다. 이것은 Configuration으로부터
+ 당신의 SessionFactory를 빌드 시키는 한 줄의 시작 코드를 절약해준다. 컨테이너는 당신의 HibernateService를
+ 시작할 것이고, 또한 이상적으로 서비스 의존성들을 처리할 것이다(데이터소스는 Hibernate가 시작되기 전에 이용 가능해야 한다).
+
+
+
+
+
+ 당신의 환경에 따라, 당신은 당신의 어플리케이션 서버가 "connection containment(연결 봉쇄)" 예외상황들을 보일 경우에 구성 옵션
+ hibernate.connection.aggressive_release를 true로 설정해야 될 수도 있다.
+
+
+
+ 트랜잭션 방도 구성
+
+
+ Hibernate Session API는 당신의 아카텍처 내에서 임의의 트랜잭션 관할 시스템에 독립적이다. 만일
+ 당신이 Hibernate로 하여금 커넥션 풀을 통해 직접 JDBC를 사용하도록 강제할 경우, 당신은 JDBC API를 호출하여 당신의 트랜잭션을
+ 시작하고 끝낼 수 있다. 만일 당신이 J2EE 어플리케이션 서버를 실행 중이라면, 당신은 필요할 때 bean-managed 트랜잭션들을 사용하고
+ JTA API와 UserTransaction을 호출하고자 원할 수 있다.
+
+
+
+ 이들 두 개의 (그리고 다른) 환경들에서 당신의 코드에 이식성을 유지하기 위해 우리는 기본 시스템을 포장하고 은폐시키는 선택적인
+ Hibernate Transaction API를 권장한다. 당신은 Hibernate 구성 프로퍼티 hibernate.transaction.factory_class를
+ 사용하여 Transaction 인스턴스들에 대한 팩토리 클래스를 지정해야 한다.
+
+
+
+ 세 개의 표준(미리 만들어진) 선택들이 존재한다:
+
+
+
+
+ org.hibernate.transaction.JDBCTransactionFactory
+
+ 데이터베이스 (JDBC) 트랜잭션들에게 위임시킨다(디폴트)
+
+
+
+ org.hibernate.transaction.JTATransactionFactory
+
+
+ 기존의 트랜잭션이 이 컨텍스트(예를 들면 EJB session bean 메소드) 내에서 진행 중일 경우에
+ container-managed transaction에게 위임시키고, 그 밖의 경우 새로운 트랜잭션이 시작되고
+ bean-managed transaction이 사용된다.
+
+
+
+
+ org.hibernate.transaction.CMTTransactionFactory
+
+ container-managed JTA 트랜잭션들에게 위임시킨다
+
+
+
+
+
+ 당신은 또한 당신 자신의 트랜잭션 방도들(예를 들면 CORBA 트랜잭션 서비스)을 정의할 수도 있다.
+
+
+
+ Hibernate에 있는 몇몇 특징들(예를 들면. second level 캐시, 자동적인 JTA 및 Session 바인딩, 기타)은 관리되는 환경에서
+ JTA TransactionManager에 대한 접근을 필요로 한다. 어플리케이션 서버에서 당신은 Hibernate가
+ TransactionManager에 대한 참조를 획득하는 방법을 지정해야 한다. 왜냐하면 J2EE가 한 개의 메커니즘을
+ 표준화 시키고 있지 않기 때문이다:
+
+
+
+
+
+
+
+ JNDI-bound SessionFactory
+
+
+ 하나의 JNDI 바인드된 Hibernate SessionFactory는 그 팩토리에 대한 룩업과 새로운
+ Session들의 생성을 단순화 시킬 수 있다. 이것은 JNDI 바인드된 Datasource에
+ 관련되어 있지 않고, 단순하게 둘 다 동일한 레지스트리를 사용한다는 점을 노트하라!
+
+
+
+ 만일 당신이 SessionFactory를 하나의 JNDI namespace에 바인드 시키고자 원할 경우,
+ hibernate.session_factory_name 프로퍼티를 사용하여 한 개의 이름(예를 들면.
+ java:hibernate/SessionFactory)을 지정하라. 만일 이 프로퍼티가 생략될 경우,
+ SessionFactory는 JNDI에 바인드 되지 않을 것이다. (이것은 읽기-전용 JNDI 디폴트
+ 구현을 가진 환경들, 예를 들면 Tomcat에서 특히 유용하다.)
+
+
+
+ SessionFactory를 JNDI에 바인드 시킬 때, Hibernate는 초기 컨텍스트를 초기화 시키기 위해
+ hibernate.jndi.url, hibernate.jndi.class의 값들을 사용할 것이다.
+ 만일 그것들이 지정되어 있지 않을 경우, 디폴트 InitialContext가 사용될 것이다.
+
+
+
+ Hibernate는 당신이 cfg.buildSessionFactory()를 호출한 후에 SessionFactory를 JNDI 내에
+ 자동적으로 위치지울 것이다. 이것은 당신이 (나중에 논의되는) HibernateService를 가진 JMX 배치를
+ 사용하지 않는 한, 당신이 적어도 당신의 어플리케이션 내에 있는 어떤 시작 코드 (또는 유틸리티 클래스) 내에서 이것을 호출할 것임을
+ 의미한다.
+
+
+
+ 만일 당신이 하나의 JNDI SessionFactory를 사용할 경우, 하나의 EJB 또는 어떤 다른 클래스는 JNDI
+ 룩업을 사용하여 SessionFactory를 얻을 수 있다. 만일 당신이 제 1장에서 소개된 하나의 Singleton
+ 레지스트리로서 행동하는 HibernateUtil helper 클래스를 사용할 경우 이 셋업이 필수적이지 않음을
+ 노트하라. 하지만 HibernateUtil은 관리되지 않는 환경에서 보다 공통적이다.
+
+
+
+
+
+ 자동적인 JTA 및 Session 바인딩
+
+
+ 관리되지 않는 환경들에서 우리는 static SessionFactory를 가진 HibernateUtil,
+ 그리고 Hibernate Session에 대한 ThreadLocal 관리를 제안했다. 몇몇 EJB들이
+ 동일 트랜잭션 내에서 실행되지만 동일 쓰레드 내에서 실행되지 않을 수 있으므로, 이 접근법은 EJB 환경에서 사용하기가 쉽지 않다. 우리는
+ 당신이 관리되는 환경에서 SessionFactory를 JNDI에 바인드 시키는 것을 권장한다.
+
+
+
+ 당신 자신의 ThreadLocal 유틸리티를 조작하는 대신, Hibernate Session을
+ 얻는데 SessionFactory 상의 getCurrentSession() 메소드를 사용하라.
+ 만일 현재의 JTA 트랜잭션 내에 Hibernate Session이 존재하지 않을 경우, 세션이 시작되고 할당될 것이다.
+ hibernate.transaction.flush_before_completion과
+ hibernate.transaction.auto_close_session 구성 옵션 둘 다 당신이
+ getCurrentSession()으로 검색하는 모든 Session에 대해 자동적으로 설정될
+ 것이고, 따라서 세션들은 또한 컨테이너가 JTA 트랜잭션들을 끝낼 때 자동적으로 flush되고 닫혀질 것이다.
+
+
+
+ 예를 들어 만일 당신이 당신의 영속 계층을 작성하는데 DAO 디자인 패턴을 사용할 경우, 모든 DAO는 필요할 때 SessionFactory를
+ 룩업하고 "현재(current)" Session을 연다. 제어 코드와 DAO 코드 사이에서 SessionFactory 또는
+ Session의 인스턴스들을 전달할 필요가 없다.
+
+
+
+
+
+ JMX 배치
+
+
+ cfg.buildSessionFactory() 줄은 여전히 JNDI에 붙은 하나의 SessionFactory를 얻기 위해
+ 어딘가에서 실행되어야 한다. 당신은 (HibernateUtil 내에 있는 것처럼) static initializer
+ 블록 속에서 이것을 행할 수 있거나 당신은 Hibernate를 managed service로서 배치할 수 있다.
+
+
+
+ Hibernate는 JBoss AS와 같은 JMX 가용성들을 가진 어플리케이션 서버 상의 배치를 위해 org.hibernate.jmx.HibernateService를
+ 배포하고 있다. 실제 배치와 구성은 벤더 지정적이다. 다음은 JBoss 4.0.x를 위한 jboss-service.xml 예제이다:
+
+
+
+
+
+
+
+
+ jboss.jca:service=RARDeployer
+ jboss.jca:service=LocalTxCM,name=HsqlDS
+
+
+ java:/hibernate/SessionFactory
+
+
+ java:HsqlDS
+ org.hibernate.dialect.HSQLDialect
+
+
+
+ org.hibernate.transaction.JTATransactionFactory
+
+ org.hibernate.transaction.JBossTransactionManagerLookup
+ true
+ true
+
+
+ 5
+
+
+ true
+ org.hibernate.cache.EhCacheProvider
+ true
+
+
+ true
+
+
+ auction/Item.hbm.xml,auction/Category.hbm.xml
+
+
+
+]]>
+
+
+ 이 파일은 META-INF로 명명된 디렉토리 속에 배치되고 확장자 .sar
+ (service archive)를 가진 한 개의 JAR 파일 속에 패키징된다. 당신은 또한 Hibernate, 그것의 필요한 제 3의 라이브러리들, 당신의 컴파일된
+ 영속 클래스들 뿐만 아니라 당신의 매핑 파일들을 동일한 아카이브 속에 패키징할 필요가 있다. 당신의 엔터프라이즈 빈즈(대개 session beans)는
+ 그것들 자신의 JAR 파일 속에 유지될 수 있지만, 당신은 한 개의 (hot-)배치 가능한 단위를 얻기 위해 메인 서비스 아카이브 속에 이 EJB JAR 파일을
+ 포함시킬 수도 있다. JMX 서비스와 EJB 배치에 관한 추가 정보는 JBoss AS 문서를 참조하라.
+
+
+
+
+
+
+
+
diff --git a/reference/ko/modules/events.xml b/reference/ko/modules/events.xml
new file mode 100644
index 0000000000..b4383187f0
--- /dev/null
+++ b/reference/ko/modules/events.xml
@@ -0,0 +1,219 @@
+
+ 인터셉터들과 이벤트들
+
+
+ 어플리케이션이 Hibernate 내부에서 발생하는 어떤 이벤트들에 대해 반응하는 것에 흔히 유용하다. 이것은 어떤 종류의 일반적인 기능,
+ 그리고 Hibernate의 확장 기능의 구현을 허용해준다.
+
+
+
+ 인터셉터들
+
+
+ Interceptor 인터페이스는 영속 객체가 저장되고, 업데이트되고, 삭제되거나 로드되기 전에 영속 객체의
+ 프로퍼티들을 조사하고/하거나 처리하는 것을 어플리케이션에 허용해줌으로써 세션으로부터 어플리케이션으로의 콜백들을 제공한다.
+ 이것에 대한 한 가지 가능한 사용은 감사 정보를 추적하는 것이다. 예를 들어, 다음 Interceptor는
+ Auditable이 생성될 때 createTimestamp를 자동적으로 설정하고
+ Auditable이 업데이트될 때 lastUpdateTimestamp 프로퍼티를 업데이트 한다.
+
+
+
+
+
+ 세션이 생성될 때 인터셉터가 지정될 것이다.
+
+
+
+
+
+ 당신은 또한 Configuration을 사용하여 인터셉터를 전역 레벨 상에 설정할 수도 있다:
+
+
+
+
+
+
+
+ 이벤트 시스템
+
+
+ 만일 당신이 당신의 영속 계층에서 특별한 이벤트들에 대해 반응해야 한다면, 당신은 또한 Hibernate3 이벤트
+ 아키텍처를 사용할 수도 있다. 이벤트 시스템은 부가물로 사용될 수 있거나 인터셉터들에 대한 대체물로 사용될 수 있다.
+
+
+
+ 본질적으로 Session 인터페이스의 모든 메소드들은 이벤트와 서로 관련되어 있다. 당신은 LoadEvent,
+ FlushEvent, 등을 갖는다 (정의된 이벤트 타입들의 전체 리스트에 대해서는 XML 구성 파일 DTD 또는
+ org.hibernate.event 패키지를 참조하라). 하나의 요청이 이들 메소드들 중 하나에 의해 만들어질 때,
+ Hibernate Session은 적절한 이벤트를 생성시키고 그것을 그 타입에 대한 구성된 이벤트 리스너에게 전달한다.
+ 박싱없이, 이들 리스너들은 그들 메소드들이 항상 귀결되었던 동일한 프로세싱을 구현한다. 하지만 당신이 리스너 인터페이스들 중 하나의 맞춤을
+ 구현하는 것이 자유롭고(예를 들어 LoadEvent는 LoadEventListener 인터페이스의
+ 등록된 구현에 의해 처리된다), 그 경우에 그들 구현은 Session에 대해 행해진 임의의 load()
+ 요청들을 처리할 책임이 있을 것이다.
+
+
+
+ 리스너들은 효율적이게끔 싱글톤(singleton)들로 간주되어야 할 것이다; 이것은 그것들이 요청들 사이에서 공유되고, 따라서 임의의 상태를
+ 인스턴스 변수들로서 저장하지 말아야 함을 의미한다.
+
+
+
+ 맞춤형 리스너는 그것이 편의적인 기저 클래스들(또는 리스너들이 이 용도로 final이 아닌 것으로 선언되므로 Hibernate
+ out-of-the-box에 의해 사용된 디폴트 이벤트 리스너들) 중 하나를 처리하고자 그리고/또는 확장하고자 원하는 이벤트들에 대해
+ 적절한 인터페이스를 구현해야 한다. 맞춤형 리스너들은 Configuration 객체를 통해 프로그램 상으로
+ 등록될 수 있거나, Hibernate 구성 XML 속에 지정될 수 있다 (properties 파일을 통한 선언적인 구성은 지원되지 않는다).
+ 다음은 맞춤형 load 이벤트 리스너에 대한 예제이다:
+
+
+
+
+
+ 당신은 또한 디폴트 리스너 대신에 해당 리스너를 사용하도록 Hibernate에게 알려주는 구성 엔트리를 필요로 한다:
+
+
+
+
+ ...
+
+
+]]>
+
+
+ 대신에 당신은 그것을 프로그래밍 방식으로 등록할 수도 있다:
+
+
+
+
+
+ 선언적으로 등록된 리스너들은 인스턴스들을 공유할 수 없다. 만일 동일한 클래스 이름이 여러 <listener/>
+ 요소들에서 사용될 경우, 각각의 참조는 그 클래스에 대한 별도의 인스턴스로 귀결될 것이다. 만일 당신이 리스너 타입들 사이에서 리스너 인스턴스들을
+ 공유할 가용성을 필요로 할 경우 당신은 프로그래밍 방식의 등록 접근법을 사용해야 한다.
+
+
+
+ 컨피그레이션 동안에 왜 인터페이스를 구현하고 특정 타입을 지정하는가? 물론 리스너 구현은 여러 개의 이벤트 리스너 인터페이스들을
+ 구현할 수 있다. 등록 동안에 추가적으로 타입을 정의하는 것은 컨피그레이션 동안에 맞춤형 리스너들의 사용 여부를 전환시키는 것을
+ 더 쉽게 해준다.
+
+
+
+
+
+ Hibernate 선언적인 보안
+
+ 대개 Hibernate 어플리케이션들에서 선언적인 보안은 session facade 계층 내에서 관리된다. 이제, Hibernate3는 어떤 액션들이
+ JACC를 통해 퍼미션을 주어지고, JAAS를 통해 인가되는 것을 허용해준다. 이것은 모든 아키텍처의 상단에 빌드된 옵션 기능이다.
+
+
+
+ 먼저, 당신은 JAAS authorization 사용을 이용 가능하도록 하기 위해 적절한 이벤트 리스터들을 구성해야 한다.
+
+
+
+
+
+]]>
+
+
+ 다음으로, 여전히 hibernate.cfg.xml 내에서 퍼미션들을 role들에 바인드 시킨다 :
+
+
+
+]]>
+
+
+ 역할(role) 이름들은 당신의 JACC 프로바이더에 의해 인지된 역할(role)들이다.
+
+
+
+
+
+
diff --git a/reference/ko/modules/example_mappings.xml b/reference/ko/modules/example_mappings.xml
new file mode 100644
index 0000000000..361dec1fac
--- /dev/null
+++ b/reference/ko/modules/example_mappings.xml
@@ -0,0 +1,652 @@
+
+ 예제: 여러 가지 매핑들
+
+
+ 이 장은 몇몇 보다 복잡한 연관 매핑들을 보여준다.
+
+
+
+ Employer/Employee
+
+
+ Employer와 Employee 사이의 관계에 대한 다음 모형은 그 연관를 표현하는 데
+ 실제 엔티티 클래스(Employment)를 사용한다. 동일한 두 부분들에 대해 하나 이상의 채용 주기가 존재할 수 있기
+ 때문에 이것이 행해진다. 컴포넌트들이 화폐 값들과 종업원 이름들을 모형화 시키는데 사용된다.
+
+
+
+
+
+
+
+
+
+
+
+
+ 다음은 가능한 매핑 문서이다:
+
+
+
+
+
+
+
+ employer_id_seq
+
+
+
+
+
+
+
+
+
+ employment_id_seq
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ employee_id_seq
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ 그리고 다음은 SchemaExport에 의해 생성된 테이블 스키마이다.
+
+
+
+
+
+
+
+ Author/Work
+
+
+ Work, Author 그리고 Person 사이의 관계들에 대한
+ 다음 모형을 검토하자. 우리는 Work과 Author 사이의 관계를 many-to-many
+ 연관으로 표현한다. 우리는 Author와 Person 사이의 관계를 one-to-one
+ 연관으로 표현하고자 선택한다. 또 다른 가능성은 Author가 Person을 확장하도록
+ 하는 것일 것이다.
+
+
+
+
+
+
+
+
+
+
+
+
+ 다음 매핑 문서는 이들 관계들을 정확하게 표현한다:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ 이 매핑에는 네 개의 테이블들이 존재한다. works, authors와
+ persons은 각각 작업 데이터, 저자 데이터, 개인 데이터를 보관한다. author_work는
+ 저자들을 작업들에 연결시키는 연관 테이블이다. 다음은 SchemaExport에 의해 생성된 테이블
+ 스키마이다.
+
+
+
+
+
+
+
+ Customer/Order/Product
+
+
+ 이제 Customer, Order와 LineItem
+ 그리고 Product 사이의 관계들에 관한 모형을 검토하자. Customer와
+ Order 사이의 one-to-many 연관이 존재하지만, 우리는 어떻게
+ Order / LineItem / Product를
+ 표현할 것인가? 나는 Order와 Product 사이의 many-to-many
+ 연관를 나타내는 하나의 연관 클래스로서 LineItem을 매핑하기로 선택했다. Hibernate에서
+ 이것은 composite 요소로 명명된다.
+
+
+
+
+
+
+
+
+
+
+
+
+ 매핑 문서:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ customers, orders, line_items 그리고
+ products는 각각 고객 데이터, 주문 데이터, 주문 라인 아이템 데이터, 그리고 제품 데이터를
+ 보관한다. line_items는 또한 주문들을 제품들과 연결시키는 연관 테이블로서 동작한다.
+
+
+
+
+
+
+
+ 기타 예제 매핑들
+
+
+ 이들 예제들은 모두 Hiberante test suite로부터 취했다. 당신은 거기서 많은
+ 다른 유용한 예제 매핑들을 발견할 것이다. Hibernate 배포본의 test
+ 폴더를 살펴보라.
+
+
+ TODO: 이 내용을 둘러싼 말들을 집어넣을 것.
+
+
+ "형식화된(Typed)" one-to-one 연관
+
+
+
+ name
+ 'HOME'
+
+
+ name
+ 'MAILING'
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+ Composite 키 예제
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ( select sum(li.quantity*p.price)
+ from LineItem li, Product p
+ where li.productId = p.productId
+ and li.customerId = customerId
+ and li.orderNumber = orderNumber )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ( select sum(li.quantity)
+ from LineItem li
+ where li.productId = productId )
+
+
+
+]]>
+
+
+
+ 공유된 합성 키 속성을 가진 Many-to-many
+
+
+
+
+
+
+
+
+
+
+
+
+ org
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org
+
+
+
+]]>
+
+
+
+ 내용 기반 판별
+
+
+
+
+
+
+
+
+
+ case
+ when title is not null then 'E'
+ when salesperson is not null then 'C'
+ else 'P'
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+ 대체 키들에 대한 연관들
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+
+
+
diff --git a/reference/ko/modules/example_parentchild.xml b/reference/ko/modules/example_parentchild.xml
new file mode 100644
index 0000000000..ac6db9986e
--- /dev/null
+++ b/reference/ko/modules/example_parentchild.xml
@@ -0,0 +1,343 @@
+
+ 예제: 부모/자식
+
+
+ 새로운 사용자들이 Hibernate로 행하고자 시도하는 바로 첫 번째 것들 중 하나는 부모/자식 타입의 관계를 모형화 시키는 것이다. 이것에 대한
+ 두 가지 다른 접근법들이 존재한다. 여러가지 이유들로 인해 특히 새로운 사용자들에게 가장 편한 접근법은 Parent로부터
+ Child로의 <one-to-many> 연관을 가진 엔티티 클래스들로서 Parent와
+ Child 양자를 모형화 시키는 것이다. (다른 접근법은 Child를
+ <composite-element>로 선언하는 것이다.) 이제, (Hibernate에서) one to many 연관에 대한 디폴트
+ 의미는 composite 요소 매핑의 의미보다 부모/자식 관계의 통상적인 의미에 훨씬 덜 가깝다는 것이 판명된다. 우리는 부모/자식 관계를 효율적이고
+ 강력하게 모형화 시키기 위해 케스케이드들을 가진 양방향 one to many 연관을 사용하는 방법을 설명할 것이다.
+ 그것은 전혀 어렵지 않다!
+
+
+
+ 콜렉션들에 관한 노트
+
+
+ Hibernate 콜렉션들은 그것들의 소유하고 있는 엔티티의 논리적 부분으로 간주된다; 결코 포함된 엔티티들의 부분이 아니다. 이것은
+ 중대한 구분점이다! 그것은 다음은 다음 결과들을 갖는다:
+
+
+
+
+
+ 콜렉션으로부터 객체를 제거하고/콜렉션에 객체를 추가 시킬 때, 콜렉션 소유자의 버전 번호가 증가된다.
+
+
+
+
+ 만일 콜렉션으로부터 제거되었던 객체가 하나의 값 타입의 인스턴스(예를 들어 composite 요소)이면, 그 객체는 영속상태를 끝내고
+ 그것의 상태가 데이터베이스로부터 완전히 제거될 것이다. 마찬가지로 하나의 값 타입의 인스턴스를 콜렉션에 추가시키는 것은 그것의
+ 상태가 즉시 영속화 되도록 강제시킬 것이다.
+
+
+
+
+ 반면에, 만일 엔티티가 콜렉션으로부터 제거될 경우(one-to-many 또는 many-to-many 연관), 그것은 디폴트로 삭제되지 않을
+ 것이다. 이 특징은 완전하게 일관적이다 - 다른 엔티티의 내부 상태에 대한 변경은 연관된 엔티티를 사라지도록 강제하지 않을 것이다!
+ 마찬가지로 콜렉션에 엔티티를 추가시키는 것은 디폴트로 그 엔티티가 영속화 되도록 강제시키지 않는다.
+
+
+
+
+
+ 대신에 콜렉션으로의 엔티티 추가가 두 엔티티들 사이에 단지 하나의 링크를 생성시키는 반면에, 그것을 제거하는 것은 링크를 제거한다는 점이
+ 디폴트 특징이다. 이것은 모든 종류의 경우들에 대해 매우 적절하다. 그것이 전혀 적절하지 않은 곳은 부모/자식 관계인 경우이고, 여기서
+ 자식의 생애는 부모의 생명주기에 묶여져 있다.
+
+
+
+
+
+ 양방향 one-to-many
+
+
+ Parent로부터 Child로의 간단한 <one-to-many>
+ 연관관계로 시작한다고 가정하자.
+
+
+
+
+
+]]>
+
+
+ 우리가 다음 코드를 실행시켰다면
+
+
+
+
+
+ Hibernate는 두 개의 SQL 문장들을 실행할 것이다:
+
+
+
+
+ c에 대한 레코드를 생성시키는 INSERT
+
+
+ p로부터 c로의 링크를 생성시키는 UPDATE
+
+
+
+
+ 이것은 비효율적일 뿐만 아니라, 또한 parent_id 컬럼 상의 임의의 NOT NULL
+ 컨스트레인트에 위배된다. 우리는 콜렉션 매핑에서 not-null="true"를 지정함으로써 null 허용 가능
+ 컨스트레인트 위반을 정정할 수 있다:
+
+
+
+
+
+]]>
+
+
+ 하지만 이것은 권장되는 해결책이 아니다.
+
+
+ 이 행위의 기본 원인은 p로부터 c로의 링크(foreign key parent_id)가
+ Child 객체의 상태의 부분으로 간주되지 않고 그러므로 INSERT로 생성되지 않는다는
+ 점이다. 따라서 해결책은 Child 매핑의 링크 부분을 만드는 것이다.
+
+
+ ]]>
+
+
+ (우리는 또한 parent 프로퍼티를 Child 클래스에 추가시킬 필요가 있다.)
+
+
+
+ 이제 Child 엔티티가 링크의 상태를 관리한다는 점을 노트하고, 우리는 링크를 업데이트 시키지 말도록 콜렉션에게
+ 통보한다. 우리는 inverse 속성을 사용한다.
+
+
+
+
+
+]]>
+
+
+ 다음 코드는 새로운 Child를 추가시키는데 사용될 것이다
+
+
+
+
+
+ 그리고 이제, 유일하게 한 개의 SQL INSERT가 실행될 것이다!
+
+
+
+ 약간 거칠게, 우리는 Parent의 addChild() 메소드를 생성시킬 수 있다.
+
+
+
+
+
+ 이제, Child를 추가하는 코드는 다음과 같다
+
+
+
+
+
+
+
+ 케스케이딩 생명주기
+
+
+ save()에 대한 명시적인 호출은 여전히 성가시다. 우리는 케스케이딩을 사용하여 이것을 얘기할 것이다.
+
+
+
+
+
+]]>
+
+
+ 다음은 위의 코드를 단순화 시킨다
+
+
+
+
+
+ 유사하게, 우리는 Parent를 저장하거나 삭제할 때 자식들에 대해 반복하는 것을 필요로 하지 않는다. 다음은
+ 데이터베이스로부터 p와 모든 그것의 자식들을 제거시킨다.
+
+
+
+
+
+ 하지만, 다음 코드
+
+
+
+
+
+ 는 데이터베이스로부터 c를 제거하지 않을 것이다; 그것은 오직 p에 대한 링크만을 제거할
+ 것이다(그리고 이 경우에 NOT NULL 컨스트레인트 위반을 일으킬 것이다 ). 당신은 명시적으로
+ Child를 delete() 시킬 필요가 있다.
+
+
+
+
+
+ 이제 우리의 경우에 Child는 그것의 부모 없이는 진정으로 존재할 수 없다. 따라서 만일 우리가 콜렉션으로부터
+ 하나의 Child를 제거할 경우, 우리는 그것이 정말로 삭제되기를 원한다. 이를 위해 우리는
+ cascade="all-delete-orphan"을 사용해야 한다.
+
+
+
+
+
+]]>
+
+
+ 노트: 비록 콜렉션 매핑이 inverse="true"를 지정할 지라도, 케스케이드들은 여전히 콜렉션 요소들을
+ 반복함으로써 처리된다. 따라서 객체가 케스케이드에 의해 저장되고, 삭제되거나 업데이트 되는 것을 당신이 필요로 할 경우, 당신은
+ 그것을 그 콜렉션에 추가해야 한다. 단순히 setParent()를 호출하는 것으로는 충분하지 않다.
+
+
+
+
+
+ 케스케이드들과 unsaved-value
+
+
+ 우리가 하나의 Session 속에 Parent를 로드시켰고 UI 액션에서 어떤 변경들을 행했고,
+ update()를 호출하여 새로운 세션에서 이들 변경들을 영속화 시키는 것을 원한다고 가정하자. Parent는
+ 자식들을 가진 콜렉션을 포함할 것이고, 케스케이딩 업데이트가 사용 가능하기 때문에, Hibernate는 어느 자식들이 새로이 초기화 되는지
+ 그리고 어느 것이 데이터베이스에서 현재 행들을 표현하는지를 알 필요가 있다. Parent와 Child
+ 모두 Long 타입의 식별자 프로퍼티들을 생성시켰다고 가정하자. Hibernate는 어느 자식들이 새로운 것인지를
+ 결정하는데 식별자와 version/timestamp 프로퍼티 값을 사용할 것이다.(을 보라.)
+ Hibernate3에서는unsaved-value를 더이상 명시적으로 지정할 필요가 없다.
+
+
+
+ 다음 코드는 parent와 child를 업데이트하고 newChild를
+ 삽입시킬 것이다.
+
+
+
+
+
+ 물론 그것은 생성되는 식별자의 경우에는 모두 매우 좋지만, 할당되는 식별자들과 composite 식별자들에 대해서는 어떠한가? 이것은 보다
+ 어렵다. 왜냐하면 Hibernate는 (사용자에 의해 할당된 식별자를 가진) 새로이 초기화 된 객체와 이전 세션에서 로드되었던 객체 사이를
+ 구별짓는데 식별자 프로퍼티를 사용할 수 없기 때문이다. 이 경우에, Hibernate는 timestamp 프로퍼티 또는 version 프로퍼티를
+ 사용하거나 실제로 second-level 캐시를 질의하거나 가장 나쁜 경우에는 행이 존재하는지를 알기 위해 데이터베이스를 질의할 것이다.
+
+
+
+
+
+
+ 결론
+
+
+ 여기에 숙지할 것이 약간 있고 그것은 처음에는 혼동스러운 것처럼 보일 수 있다. 하지만 실제로 그것은 모두 매우 좋게 동작한다. 대부분의
+ Hibernate 어플리케이션들은 많은 장소들에서 부모/자식 패턴을 사용한다.
+
+
+
+ 우리는 첫 번째 단락에서 대안을 언급했다. 위의 쟁점들 중 어느 것도 정확하게 부모/자식 관계의 의미를 가진,
+ <composite-element> 매핑들의 경우에는 존재하지 않는다. 불행히도, composite 요소 클래스들에
+ 대한 두 개의 커다란 제약들이 존재한다: composite 요소들은 콜렉션들을 소유하지 않고, 그것들은 유일한 부모가 아닌 다른 어떤
+ 엔티티의 자식일 수는 없다.
+
+
+
+
+
\ No newline at end of file
diff --git a/reference/ko/modules/example_weblog.xml b/reference/ko/modules/example_weblog.xml
new file mode 100644
index 0000000000..8db2aa24f6
--- /dev/null
+++ b/reference/ko/modules/example_weblog.xml
@@ -0,0 +1,428 @@
+
+ 예제: Weblog 어플리케이션
+
+
+ 영속 클래스들
+
+
+ 영속 클래스들은 웹로그, 그리고 웹 로그 내에 게시된 항목을 표현한다.그것들은
+ 표준 부모/자식 관계로 모형화 될 것이지만, 우리는 set 대신에 순서지워진 bag를 사용할 것이다.
+
+
+
+
+
+
+
+
+
+ Hibernate 매핑들
+
+
+ XML 매핑들은 이제 매우 간단해질 것이다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+
+ Hibernate 코드
+
+
+ 다음 클래스는 우리가 Hibernate를 사용하여 이들 클래스들로 행할 수 있는 몇몇 종류의 것들을 설명한다.
+
+
+ :minDate"
+ );
+
+ Calendar cal = Calendar.getInstance();
+ cal.roll(Calendar.MONTH, false);
+ q.setCalendar("minDate", cal);
+
+ result = q.list();
+ tx.commit();
+ }
+ catch (HibernateException he) {
+ if (tx!=null) tx.rollback();
+ throw he;
+ }
+ finally {
+ session.close();
+ }
+ return result;
+ }
+}]]>
+
+
+
+
+
diff --git a/reference/ko/modules/filters.xml b/reference/ko/modules/filters.xml
new file mode 100644
index 0000000000..cc5c7bf8b6
--- /dev/null
+++ b/reference/ko/modules/filters.xml
@@ -0,0 +1,123 @@
+
+ 데이터 필터링하기
+
+
+ Hibernate3은 혁신적인 "가시성(visibility)" 규칙들로서 데이터를 처리하는 새로운 접근법을 제공한다. Hibernate
+ 필터는 특정 Hibernate 세션에 대해 이용 가능하게 되거나 이용 불가능하게 될 수도 있는 전역, 명명된 파라미터화 된 필터이다.
+
+
+
+ Hibernate 필터들
+
+
+ Hibernate3은 필터 기준(criteria)을 미리 정의하고 클래스 레벨과 콜렉션 레벨 양자에서 그들 필터들을 첨부할 능력을 추가시킨다.
+ 필터 기준(criteria)은 클래스 요소와 다양한 콜렉션 요소들에 대해 이용 가능한 기존의 "where" 속성과 매우 유사한 하나의 제한 절을
+ 정의하는 능력이다. 이것들을 제외하면 필터 조건들은 파라미터화 될 수 있다. 그때 어플리케이션은 주어진 필터들이 이용 가능한지 여부
+ 그리고 그들 파라미터 값들이 무엇이어야 하는지를 실행 시에 결정할 수 있다. 필터들은 데이터베이스 뷰들 처럼 사용될 수 있지만,
+ 어플리케이션 내부에 파라미터화 된다.
+
+
+
+ 필터들을 사용하기 위해서, 그것들은 먼저 정의되고 나서 적절한 매핑 요소들에 첨가되어야 한다. 필터를 정의하기 위해,
+ <hibernate-mapping/> 요소 내부에 <filter-def/> 요소를
+ 사용하라:
+
+
+
+
+]]>
+
+
+ 그때 이 필터는 클래스에 첨가될 수 있다:
+
+
+
+ ...
+
+]]>
+
+
+ 또는 콜렉션에 첨가될 수 있다:
+
+
+
+
+]]>
+
+
+ 또는 동시에 양자에(또는 각각의 여러번) 첨가될 수 있다.
+
+
+
+ Session 상의 메소드들은 다음과 같다: enableFilter(String filterName),
+ getEnabledFilter(String filterName), disableFilter(String filterName).
+ 디폴트로, 필터들은 주어진 세션에 대해 이용 가능하지 않다; 그것들은 Session.enabledFilter()
+ 메소드의 사용을 통해 명시적으로 이용 가능하게 되어야 한다. Session.enabledFilter()는
+ Filter 인터페이스의 인스턴스를 반환한다. 위에 정의된 간단한 필터를 사용하면, 이것은 다음과 같을 것이다:
+
+
+
+
+
+ org.hibernate.Filter 인터페이스 상의 메소드들은 Hibernate에 매우 공통된 method-chaining을 허용한다는 점을 노트하라.
+
+
+
+ 유효한 기록 날짜 패턴을 가진 시간 데이터를 사용하는 전체 예제 :
+
+
+
+
+
+
+
+...
+
+
+
+...
+
+
+
+
+
+...
+
+
+
+
+
+]]>
+
+
+ 그때 당신이 현재 유효한 레코드들을 항상 얻는 것을 확실히 하기 위해, employee 데이터를 검색하기 전에 세션 상에 필터를
+ 간단하게 이용 가능하게 하라:
+
+
+ :targetSalary")
+ .setLong("targetSalary", new Long(1000000))
+ .list();
+]]>
+
+
+ 위의 HQL 에서, 심지어 비록 우리가 결과들에 대한 봉급 컨스트레인트를 명시적으로 언급만 했을지라도, 이용 가능한 필터 때문에
+ 그 질의는 봉급이 백만달러 이상인 현재 채용중인 직원들만을 반환할 것이다.
+
+
+
+ 노트: 만일 당신이 outer 조인에 대해 필터들을 사용할 계획이라면 (HQL이든 로드 페칭이든) 조건 표현식의 방향을 주의하라.
+ 이것을 left outer join으로 설정하는 것이 가장 안전하다; 일반적으로 오퍼레이터 뒤에 있는 컬럼 이름(들)이 뒤따르는 첫번째에
+ 파라미터를 위치지워라.
+
+
+
+
+
+
diff --git a/reference/ko/modules/inheritance_mapping.xml b/reference/ko/modules/inheritance_mapping.xml
new file mode 100644
index 0000000000..9c330a86de
--- /dev/null
+++ b/reference/ko/modules/inheritance_mapping.xml
@@ -0,0 +1,436 @@
+
+ 상속 매핑
+
+
+ 세 가지 방도들
+
+
+ Hibernate는 세 가지 기본적인 상속 매핑 방도들을 지원한다:
+
+
+
+
+
+ table per class hierarchy
+
+
+
+
+ table per subclass
+
+
+
+
+ table per concrete class
+
+
+
+
+
+ 게다가 Hibernate는 네 번째의 약간 다른 종류의 다형성을 지원한다:
+
+
+
+
+
+ implicit polymorphism(함축적인 다형성)
+
+
+
+
+
+ 동일한 상속 계층구조의 다른 가지들에 대해 다른 매핑 방도들을 사용하는 것이 가능하고, 그런 다음 전체 계층 구조를 가로질러
+ 다형성을 성취하는데 함축적인 다형성을 사용하라. 하지만 Hibernate는 동일한 루트 <class> 요소
+ 하에서 <subclass> 그리고 <joined-subclass> 그리고
+ <union-subclass> 매핑들을 혼합하는 것을 지원하지 않는다. 동일한 <class>
+ 요소 하에서 <subclass> 요소와 <join> 요소를 결합시킴으로써
+ table per hierarchy 방도와 table per subclass 방도를 함께 혼합시키는 것이 가능하다(아래를 보라).
+
+
+
+ Table per class hierarchy
+
+
+ 우리가 CreditCardPayment, CashPayment, ChequePayment
+ 구현자들을 가진 하나의 인터페이스 Payment를 갖고 있다고 가정하자. table per hierarchy 매핑은
+ 다음과 같을 것이다:
+
+
+
+
+
+
+
+
+ ...
+
+
+ ...
+
+
+ ...
+
+
+ ...
+
+]]>
+
+
+ 정확히 하나의 테이블이 필요하다. 이 매핑 방도에는 다음의 하나의 큰 제약이 존재한다: CCTYPE과 같이,
+ 서브 클래스들에 의해 선언된 컬럼들은 NOT NULL 컨스트레인트들을 가질 수 없다.
+
+
+
+
+
+ Table per subclass
+
+
+ table per subclass 매핑은 다음과 같을 것이다:
+
+
+
+
+
+
+
+ ...
+
+
+
+ ...
+
+
+
+ ...
+
+
+
+ ...
+
+]]>
+
+
+ 네 개의 테이블들이 필요하다. 세 개의 서브클래스 테이블들은 슈퍼클래스 테이블에 대한 프라이머리 키 연관들을 갖는다
+ (따라서 그 관계형 모형은 실제로 one-to-one 연관이다).
+
+
+
+
+
+ discriminator를 사용하는, table per subclass
+
+
+ table-per-subclass에 대한 Hibernate의 구현은 discriminator(판별자) 컬럼을 필요로 하지 않음을 노트하라.
+ 다른 객체/관계형 매핑기들은 슈퍼클래스 테이블 속에 하나의 타입 판별자 컬럼을 필요로 하는 table-per-subclass에 대한 다른 구현을
+ 사용한다. Hibernate에 의해 채택된 접근법은 구현하기가 훨씬 더 어렵지만 관계형 관점에서는 아마 틀림없이 보다 더 정확하다.
+ 만일 당신이 table per subclass 방도에 대해 하나의 판별자 컬럼을 사용하고 싶다면, 당신은 다음과 같이
+ <subclass>와 <join>의 사용을 결합시킬 수도 있다:
+
+
+
+
+
+
+
+
+ ...
+
+
+
+
+ ...
+
+
+
+
+
+ ...
+
+
+
+
+
+ ...
+
+
+]]>
+
+
+ 선택적인 fetch="select" 선언은 슈퍼클래스를 질의할 때 outer join을 사용하여
+ ChequePayment 서브클래스 데이터를 페치시키지 않도록 Hibernate에게 알려준다.
+
+
+
+
+
+ table per class hierarchy와 table per subclass를 혼합하기
+
+
+ 당신은 이 접근법을 사용하여 table per hierarchy 방도와 table per subclass 방도를 혼합시킬 수 있다:
+
+
+
+
+
+
+
+
+ ...
+
+
+
+ ...
+
+
+
+ ...
+
+
+ ...
+
+]]>
+
+
+ 이들 매핑 방도들 중 어떤 것에 대해, 루트 Payment 클래스에 대한 하나의 다형성 연관은
+ <many-to-one>을 사용하여 매핑된다.
+
+
+ ]]>
+
+
+
+
+ Table per concrete class
+
+
+ 우리가 table per concrete class 방도 매핑에 대해 취할 수 있는 두 가지 방법들이 존재한다. 첫 번째는
+ <union-subclass>를 사용하는 것이다.
+
+
+
+
+
+
+
+ ...
+
+
+ ...
+
+
+ ...
+
+
+ ...
+
+]]>
+
+
+ 세 개의 테이블들이 수반된다. 각각의 테이블은 상속된 프로퍼티들을 포함하여, 그 클래스의 모든 프로퍼티들에 대한 컬럼들을 정의한다.
+
+
+
+ 이 접근법의 제약은 만일 하나의 프로퍼티가 슈퍼클래스 상으로 매핑될 경우, 그 컬럼 이름이 모든 서브클래스 테이블들 상에서 같아야 한다는
+ 점이다.(장래의 Hibernate 배포본에서 우리는 이 제약을 풀 수도 있다.) identity 생성기 방도는 union 서브클래스 상속에서 허용되지
+ 않으며, 진정 프라이머리 키 시드는 하나의 계층구조의 모든 unioned 서브클래스들을 가로질러 공유되어야 한다.
+
+
+
+
+
+ 함축적인 다형성을 사용하는, table per concrete class
+
+
+ 대안적인 접근법은 함축적인 다형성을 사용하는 것이다:
+
+
+
+
+
+
+
+ ...
+
+
+
+
+
+
+
+ ...
+
+
+
+
+
+
+
+ ...
+]]>
+
+
+ 어느 곳에서도 우리가 명시적으로 Payment 인터페이스를 언급하지 않음을 주목하라.
+ 또한 Payment의 프로퍼티들이 서브클래스들 각각에서 매핑된다는 점을 주목하라.
+ 만일 당신이 중복을 피하고자 원한다면, XML 엔티티들을 사용하는 것을 고려하라(예를 들어 매핑에서
+ DOCTYPE 선언과 &allproperties;에서
+ [ <!ENTITY allproperties SYSTEM "allproperties.xml"> ]).
+
+
+
+ 이 접근법의 단점은 다형성 질의들을 수행할 때 Hibernate가 생성된 SQl UNION들을 생성시키는
+ 않는다는 점이다.
+
+
+
+ 이 매핑 방도의 경우, Payment에 대한 하나의 다형성 연관은 대개 <any>를
+ 사용하여 매핑된다.
+
+
+
+
+
+
+
+
+]]>
+
+
+
+
+ 함축적인 다형성을 다른 상속 매핑들과 혼합하기
+
+
+ 이 매핑에 대해 주목할 하나 이상의 것이 존재한다. 서브클래스들이 그것들 자신의<class> 요소 내에
+ 각각 매핑되므로(그리고 Payment가 단지 인터페이스이므로), 서브클래스들 각각은 쉽게 또 다른 상속 계층구조의
+ 부분일 수 있다! (그리고 당신은 Payment 인터페이스에 대해 여전히 다형성 질의들을 사용할 수 있다.)
+
+
+
+
+
+
+
+
+ ...
+
+
+
+
+
+
+
+
+ ...
+
+
+
+ ...
+
+
+
+
+ ...
+
+]]>
+
+
+ 다시 한번, 우리는 Payment를 명시적으로 언급하지 않는다. 만일 우리가 Payment
+ 인터페이스에 대해 하나의 질의를 실행할 경우-예를 들어, from Payment-, Hibernate는 CreditCardPayment
+ (와 그것의 서브클래스들, 왜냐하면 그것들 또한 Payment를 구현하므로), CashPayment
+ 그리고 ChequePayment 인스턴스들을 자동적으로 반환할 것이지만
+ NonelectronicTransaction의 인스턴스들을 반환하지 않는다.
+
+
+
+
+
+
+
+ 제약들
+
+
+ table per concrete-class 매핑 방도에 대한 "함축적인 다형성" 접근법에는 어떤 제약들이 존재한다.
+ <union-subclass> 매핑들에 대해서는 다소 덜 제한적인 제약들이 존재한다:
+
+
+
+ 다음 표는 Hibernate에서 table per concrete-class 매핑들에 대한 제약들, 그리고 함축적인 다형성에 대한 제약들을 보여준다.
+
+
+
+ 상속 매핑들의 특징들
+
+
+
+
+
+
+
+
+
+
+
+ 상속 방도
+ 다형성 다대일
+ 다형성 일대일
+ 다형성 일대다
+ 다형성 다대다
+ 다형성 load()/get()
+ 다형성 질의들
+ 다형성 조인들
+ Outer 조인 페칭
+
+
+
+
+ table per class-hierarchy
+ <many-to-one>
+ <one-to-one>
+ <one-to-many>
+ <many-to-many>
+ s.get(Payment.class, id)
+ from Payment p
+ from Order o join o.payment p
+ 지원됨
+
+
+ table per subclass
+ <many-to-one>
+ <one-to-one>
+ <one-to-many>
+ <many-to-many>
+ s.get(Payment.class, id)
+ from Payment p
+ from Order o join o.payment p
+ 지원됨
+
+
+ table per concrete-class (union-subclass)
+ <many-to-one>
+ <one-to-one>
+ <one-to-many> (for inverse="true" only)
+ <many-to-many>
+ s.get(Payment.class, id)
+ from Payment p
+ from Order o join o.payment p
+ 지원됨
+
+
+ table per concrete class (implicit polymorphism)
+ <any>
+ 지원되지 않음
+ 지원되지 않음
+ <many-to-any>
+ s.createCriteria(Payment.class).add( Restrictions.idEq(id) ).uniqueResult()
+ from Payment p
+ 지원되지 않음
+ 지원되지 않음
+
+
+
+
+
+
+
+
diff --git a/reference/ko/modules/performance.xml b/reference/ko/modules/performance.xml
new file mode 100644
index 0000000000..b436502835
--- /dev/null
+++ b/reference/ko/modules/performance.xml
@@ -0,0 +1,1234 @@
+
+ 퍼포먼스 개선하기
+
+
+ 페칭 방도들
+
+
+ 페칭 방도는 어플리케이션이 연관을 네비게이트할 필요가 있을 때 Hibernate가 연관된 객체들을 검색하는데
+ 사용하게 될 방도이다.페치 방도들은 O/R 매핑 메타데이터 내에서 선언될 수 있거나 하나의 특정 HQL 또는 Criteria
+ 질의에 의해 오버라이드 될 수도 있다.
+
+
+
+ Hibernate3는 다음 페칭 방도들을 정의한다:
+
+
+
+
+
+ Join 페칭 - Hibernate는 OUTER JOIN을 사용하여 연관된 인스턴스
+ 또는 동일한 SELECT 내에서 콜렉션을 검색한다.
+
+
+
+
+ Select 페칭 - 두 번째 SELECT는 연과된 엔티티 또는 콜렉션을 검색하는데
+ 사용된다. 당신이 lazy="false"를 지정함으로써 명시적으로 lazy 페칭을 사용 불가능하게 하지 않는
+ 한, 이 두 번째 select는 당신이 그 연관에 실제로 액세스할 때 오직 실행될 것이다.
+
+
+
+
+ Subselect 페칭 - 두 번째 SELECT는 이전 질의 또는 페치에서 검색된
+ 모든 엔티티들에 대해 연관된 콜렉션들을 검색하는데 사용된다. 당신이 lazy="false"를 지정하여
+ 명시적으로 lazy 페칭을 사용 불가능하게 하지 않는 한, 이 두 번째 select는 당신이 실제로 그 연관에 접근할 때 오직 실행될
+ 것이다.
+
+
+
+
+ Batch 페칭 - select 페칭을 위한 최적화 방도 - Hibernate는 프라이머리 키들이나 foreign
+ 키들의 리스트를 지정함으로써 하나의SELECT 내에서 엔티티 인스턴스들이나 콜렉션들에 대한 batch를
+ 검색한다.
+
+
+
+
+
+ Hibernate는 또한 다음 사이를 구별 짓는다:
+
+
+
+
+
+ 즉각적인 페칭 - 소유자가 로드될 때, 연관, 콜렉션 또는 속성이 즉시 페치된다.
+
+
+
+
+ Lazy 콜렉션 페칭 - 어플리케이션이 그 콜렉션에 대해 하나의 오퍼레이션을 호출할 때
+ 콜렉션이 페치된다.(이것은 콜렉션들에 대해 디폴트이다.)
+
+
+
+
+ 프락시 페칭 - 식별자 getter가 아닌 다른 메소드가 연관된 객체에 대해 호출될 때
+ 단일 값 연관이 페치된다.
+
+
+
+
+ Lazy 속성 페칭 - 인스턴스 변수가 접근될 때 속성 또는 단일 값 연관이 페치된다(빌드 시 바이트코드
+ 수단을 필요로 한다 ). 이 접근법은 좀처럼 필요하지 않는다.
+
+
+
+
+
+ 우리는 여기서 두 개의 직교하는 개념들을 갖는다: 연관이 페치될 때, 그리고 그것이 페치되는
+ 방법(사용되는 SQL). 그것들을 혼동하지 말라! 우리는 퍼포먼스를 튜팅하는데
+ 페치를 사용한다. 우리는 특정 클래스의 어떤 detached 인스턴스 내에서 항상 이용 가능한
+ 데이터가 무엇인지에 대한 계약을 정의하는데 lazy를 사용할 수 있다.
+
+
+
+ lazy 연관들로 작업하기
+
+
+ 디폴트로 Hibernate3는 콜렉션들에 대해 lazy select 페칭을 사용하고, 단일 값 연관들에 대해 lazy
+ 프락시 페칭을 사용한다. 이들 디폴트들은 거의 모든 어플리케이션들에서 거의 모든 연관들에 대해 유의미하다.
+
+
+
+ 노트: 만일 당신이 hibernate.default_batch_fetch_size를 설정하는
+ 경우, Hibernate는 lazy 페칭을 위한 batch 페치 최적화를 사용할 것이다(이 최적화는 또한 더 많은 과립상의 레벨에서 이용 가능할
+ 수 있다).
+
+
+
+ 하지만, lazy 페칭은 당신이 알고 있어야 하는 한 가지 문제를 제기한다. 열려진 Hibernate 세션 컨텍스트 외부에서 lazy 연관에
+ 대한 접근은 예외상황으로 귀결될 것이다. 예를 들면 :
+
+
+
+
+
+ Session이 닫혔을 때 permissions 콜렉션이 초기화 되지 않았으므로, 그 콜렉션은 그것의 상태를 로드시킬
+ 수가 없을 것이다. Hibernate 는 detached 객체들에 대한 lazy 초기화를 지원하지 않는다. 정정은
+ 콜렉션으로부터 읽어들이는 코드를 커밋 바로 직전으로 이동시키는 것이다.
+
+
+
+ 다른 방법으로 연관 매핑에 대해 lazy="false"를 지정함으로써, non-lazy 콜렉션 또는
+ non-lazy 연관을 사용할 수 있다. 하지만 lazy 초기화는 거의 모든 콜렉션들과 연관들에 대해 사용되도록 고안되어 있다.
+ 만일 당신이 당신의 객체 모형 내에 너무 많은 non-lazy 연관들을 정의할 경우, Hibernate는 모든 트랜잭션에서 전체
+ 데이터베이스를 메모리 속으로 페치하는 필요성을 끝내게 될 것이다!
+
+
+
+ 다른 한편으로, 우리는 특정 트랜잭션 내에서 select 페칭 대신에 (고유하게 non-lazy인) join 페칭을 선택하기를 자주 원한다.
+ 우리는 이제 페칭 방도를 맞춤화 시키는 방법을 알게 될 것이다. Hibernate3에서, 페치 방도를 선택하는 메커니즘은 단일 값 연관들과
+ 콜렉션들에 대해 동일하다.
+
+
+
+
+
+ 페치 방도들을 튜닝하기
+
+
+ select 페칭(디폴트)은 N+1 selects 문제점들에 매우 취약해서, 우리는 매핑 문서에서 join 페칭을 사용 가능하게 하기를 원할
+ 수도 있다:
+
+
+
+
+
+
+
+ ]]>
+
+
+ 매핑 문서 내에 정의된 페치 방도는 다음에 영향을 준다:
+
+
+
+
+
+ get() 또는 load()를 통한 검색
+
+
+
+
+ 연관이 네비게이트될 때 함축적으로 발생하는 검색(lazy 페칭)
+
+
+
+
+ Criteria 질의들
+
+
+
+
+
+ 대개, 우리는 페칭을 맞춤화 시키는데 매핑 문서를 사용하지 않는다. 대신에, 우리는 디폴트 특징을 유지하고, HQL에서
+ left join fetch를 사용하여, 특정 트랜잭션에 대해 그것을 오버라이드 시킨다. 이것은
+ outer join을 사용하여 첫 번째 select에서 초기에 그 연관을 eagerly 페치시킬 것을 Hibernate에게 알려준다.
+ Criteria query API에서, 우리는 setFetchMode(FetchMode.JOIN)을
+ 사용한다.
+
+
+
+ 만일 당신이 get() 또는 load()에 의해 사용된 페칭 방도를 변경시킬 수 있기를
+ 당신이 원한다고 느낄 경우, 단순하게 Criteria 질의를 사용하라. 예를 들면:
+
+
+
+
+
+ (이것은 몇몇 ORM 솔루션들이 "페치 계획"이라고 부르는 것에 대한 Hibernate의 등가물이다.)
+
+
+
+ N+1 개의 select들을 가진 문제점들을 피하는 완전히 다른 방법은 second-level 캐시를 사용하는 것이다.
+
+
+
+
+
+ Single-ended 연관 프락시
+
+
+ 콜렉션들에 대한 Lazy 페칭은 영속 콜렉션들에 대한 Hibernate 자신의 구현을 사용하여 구현된다. 하지만 다른 메커니즘은
+ single-ended 연관들에서 lazy 특징에 필요하다. 연관의 대상 엔티티는 프락시 되어야 한다. Hibernate는
+ (훌륭한 CGLIB 라이브러리를 통해) 런타임 바이트코드 증진을 사용하여 영속 객체들에 대한 lazy 초기화 프락시들을 구현한다.
+
+
+
+ 디폴트로, Hibernate3는 모든 영속 클래스들에 대해 (시작 시에) 프락시들을 생성시키고 many-to-one
+ 연관과 one-to-one 연관에 대해 lazy 페칭을 이용 가능하게 하는데 그것들을 사용한다.
+
+
+
+ 매핑 파일은 그 클래스에 대한 프락시 인터페이스로서 사용할, proxy 속성을 가진, 인터페이스를 선언할
+ 수도 있다. 디폴트로 Hibernate는 그 클래스의 서브클래스를 사용한다. 프락시된 클래스는 최소한의 패키지 가시성
+ (visibility)을 가진 디폴트 생성자를 구현해야 함을 노트하라. 우리는 모든 영속 클래스들에 대해 이 생성자를 권장한다!
+
+
+
+ 다형성 클래스들에 대해 이 접근법을 확장할 때 의식해야 하는 몇몇 난처함들이 존재한다. 예를 들면.
+
+
+
+ ......
+
+ .....
+
+]]>
+
+
+ 첫 번째로, 심지어 기본 인스턴스가 DomesticCat의 인스턴스인 경우조차도,
+ Cat의 인스턴스들은 결코 DomesticCat으로 타입캐스트가 가능하지 않을 것이다:
+
+
+
+
+
+ 두번째로, 프락시 ==를 파기할 가능성이 있다.
+
+
+
+
+
+ 하지만, 그 경우는 보이는 만큼 그렇게 나쁘지는 않다. 심지어 우리가 이제 다른 프락시 객체들에 대한 두 개의 참조를 가질지라도,
+ 기본 인스턴스는 여전히 동일한 객체들일 것이다:
+
+
+
+
+
+ 세번째로, 당신은 final 클래스 또는 임의의 final 메소드들을 가진 클래스에
+ 대해 CGLIB 프락시를 사용하지 않을 수 있다.
+
+
+
+ 마지막으로, 만일 당신의 영속 객체가 초기화 시에 어떤 리소스들을 필요로 할 경우(예를 들어, initializer들 또는 디폴트 생성자
+ 내에서), 그때 그들 리소스들이 또한 프락시에 의해 획득될 것이다. 프락시 클래스는 영속 클래스에 대한 실제 서브클래스이다.
+
+
+
+ 이들 문제점들은 모두 자바의 단일 상속 모형의 기본적인 제약 때문이다. 만일 당신이 이들 문제점들을 피하고자 원할 경우 당신의 영속
+ 클래스들은 각각 그것의 비지니스 메소드들을 선언하는 인터페이스를 구현해야 한다. 당신은 매핑 파일 속에 이들 인터페이스들을
+ 지정해야 한다. 예를 들면.
+
+
+
+ ......
+
+ .....
+
+]]>
+
+
+ 여기서 CatImpl은 Cat 인터페이스를 구현하고 DomesticCatImpl은
+ DomesticCat 인터페이스를 구현한다. 그때 Cat과 DomesticCat의
+ 인스턴스들에 대한 프락시들은 load() 또는 iterate()에 의해 반환될 수 있다.
+ (list()가 대개 프락시들을 반환하지 않음을 노트하라.)
+
+
+
+
+
+ 관계들은 또한 lazy 초기화 된다. 이것은 당신이 임의의 프로퍼티들을 CatImpl 타입이 아닌
+ Cat 타입으로 선언해야 함을 의미한다.
+
+
+
+ 어떤 오퍼레이션들은 프락시 초기화를 필요로 하지 않는다
+
+
+
+
+
+ equals(), 만일 영속 클래스가 equals()를 오버라이드 시키지 않는 경우
+
+
+
+
+ hashCode(), 만일 영속 클래스가hashCode()를 오버라이드 시키지
+ 않는 경우
+
+
+
+
+ 식별자 getter 메소드
+
+
+
+
+
+ Hibernate는 equals() 또는 hashCode()를 오버라이드 시키는 영속 클래스들을
+ 검출할 것이다.
+
+
+
+
+
+ 콜렉션들과 프락시들을 초기화 시키기
+
+
+ 만일 초기화 되지 않은 콜렉션이나 프락시가 Session 영역의 외부에서 접근될 경우에, 예를 들어 콜렉션을
+ 소유하거나 프락시에 대한 참조를 가진 엔티티가 detached 상태에 있을 때, LazyInitializationException이
+ Hibernate에 의해 던져질 것이다.
+
+
+
+ 때때로 우리는Session을 닫기 전에 프락시 또는 콜렉션이 초기화 됨을 확실히 할 필요가 있다. 물론 우리는
+ 예를 들어 cat.getSex() 또는 cat.getKittens().size()를 호출하여 항상
+ 초기화를 강제시킬 수 있다. 그러나 그것은 코드의 독자들에게는 혼동스럽고 일반적인 코드로 편의적이지 않다.
+
+
+
+ static 메소드들 Hibernate.initialize()와 Hibernate.isInitialized()는
+ lazy 초기화 된 콜렉션들이나 프락시들에 대해 작업하는 편리한 방법을 어플리케이션에 제공한다. Hibernate.initialize(cat)은
+ 그것의 Session이 여전히 열려져 있는 한 프락시 cat의 초기화를 강제할 것이다.
+ Hibernate.initialize( cat.getKittens())는 kittens의 콜렉션에 대해 유사한 효과를 갖는다.
+
+
+
+ 또 다른 옵션은 모든 필요한 콜렉션들과 프락시들이 로드되기 전까지 Session을 열린 채로 유지하는 것이다.
+ 몇몇 어플리케이션 아키텍처들, 특히 Hibernate를 사용하여 데이터에 접근하는 코드, 그리고 다른 어플리케이션 계층들이나 다른
+ 물리적 프로세스들 내에서 그것을 사용하는 코드에서, 그것은 콜렉션이 초기화 될 때 Session이 열려져
+ 있음을 확실히 하는 문제일 수 있다. 이 쟁점을 다루는 두 가지 기본 방법들이 존재한다:
+
+
+
+
+
+ 웹 기반 어플리케이션에서, 서블릿 필터는 뷰 렌더링이 완료되는, 사용자 요청의 바로 끝에서만 Session을
+ 닫는데 사용될 수 있다(Open Session in View 패턴). 물론 이것은 당신의 어플리케이션
+ 인프라스트럭처의 예외상황 처리의 정정에 관한 무거운 요구를 부과한다. 사용자에게 반환하기 전에, 심지어 예외상황이
+ 뷰의 렌더링 동안 발생할 때, Session이 닫혀지고 트랜잭션이 종료되는 것은 지극히 중요하다.
+ 서블릿 필터는 이 접근법으로 Session에 접근하는 것이 가능해야 한다. 우리는
+ ThreadLocal 변수가 현재의 Session을 보관하는데 사용되는 것을
+ 권장한다(예제 구현에 대해서는 1장, 를 보라).
+
+
+
+
+ 별도의 비지니스 티어를 가진 어플리케이션에서, 비지니스 로직은 반환 전에 웹 티어에 필요한 모든 콜렉션들을
+ "준비"해야 한다. 이것은 비지니스 티어가 모든 데이터를 로드시키고 이미 초기화된 모든 데이터를 특정 쓰임새에
+ 필요한 프리젠테이션/웹 티어로 반환해야 함을 의미한다. 대개 어플리케이션은 웹 티어에 필요하게 될 각각의 콜렉션에
+ 대해 Hibernate.initialize()를 호출하거나(이 호출은 세션이 닫히기 전에 발생해야 한다)
+ 또는 FETCH 절을 갖거나 또는 Criteria 내에
+ FetchMode.JOIN을 가진 Hibernate 질의를 사용하여 콜렉션을 열심히 검색한다. 이것은
+ 대개 당신이 Session Facade 대신 Command 패턴을 채택할
+ 경우에 더 쉽다.
+
+
+
+
+ 당신은 또한 초기화 되지 않은 콜렉션들(또는 다른 프락시들)에 접근하기 전에 merge() 또는
+ lock()으로 앞서 로드된 객체를 새로운 Sessionn에 첨부할 수도 있다.
+ 아니다. Hibernate는 이것을 자동적으로 행하지 않고, 확실히 자동적으로 행하지 않을 것이다.
+ 왜냐하면 그것은 특별한 목적을 위한 트랜잭션 의미를 도입할 것이기 때문이다!
+
+
+
+
+
+ 때때로 당신은 거대한 콜렉션을 초기화 시키는 것을 원하지 않지만, 여전히 (그것의 사이즈와 같은) 그것에 대한 어떤 정보 또는
+ 데이터의 부분집합을 필요로 한다.
+
+
+
+ 당신은 그것을 초기화 시키지 않고서 콜렉션의 사이즈를 얻는데 콜렉션 필터를 사용할 수 있다:
+
+
+
+
+
+ createFilter() 메소드는 또한 전체 콜렉션을 초기화 시킬 필요 없이 콜렉션의 부분집합들을 효율적으로
+ 검색하는데 사용된다:
+
+
+
+
+
+
+
+ batch 페칭 사용하기
+
+
+ Hibernate는 배치 페칭을 효율적으로 사용할 수 있다. 즉 하나의 프락시가 액세스 될 경우에 Hibernate는 몇몇 초기화 되지 않은
+ 프락시들을 로드시킬 수 있다(또는 콜렉션들). batch 페칭은 lazy select 페칭 방도에 대한 최적화이다. 당신이 batch
+ 페칭을 튜닝시킬 수 있는 두 가지 방법들이 존재한다: 클래스 레벨에서 그리고 콜렉션 레벨에서.
+
+
+
+ 클래스들/엔티티들에 대한 batch 페칭은 이해하기가 더 쉽다. 당신이 실행 시에 다음 상황에 처한다고 상상하라: 당신은 하나의
+ Session 속에 로드된 25개의 Cat 인스턴스들을 갖고 있고, 각각의
+ Cat은 그것의 소유자 즉, Person에 대한 참조를
+ 갖고 있다. Person 클래스는 프락시 lazy="true"로서 매핑된다. 만일
+ 당신이 이제 모든 cat들을 통해 반복하고 각각의 cat에 대해 getOwner()를 호출할 경우, Hibernate는
+ 프락시된 소유자들을 검색하기 위해 25개의 SELECT 문장들을 디폴트로 실행시킬 것이다. 당신은
+ Person 매핑에서 batch-size를 지정함으로써 이 동작을 튜닝시킬 수 있다:
+
+
+ ...]]>
+
+
+ Hibernate는 이제 세 개의 질의들 만을 실행시킬 것이고, 그 패턴은 10,10, 5 이다.
+
+
+
+ 당신은 또한 콜렉션들에 대해 batch 페칭을 이용 가능하게 할 수도 있다. 예를 들어, 만일 각각의 Person이
+ Cat들을 가진 lazy 콜렉션을 갖고, 10개의 person들이 Sesssion 내에 현재
+ 로드되어 있을 경우, 모든 person들에 대한 반복은 10개의 SELECT들을 생성시킬 것이고, getCats()에
+ 대한 매번의 호출에 대해 하나의 SELECT를 생성시킬 것이다. 만일 당신이 Person
+ 매핑에서 cats 콜렉션에 대해 batch 페칭을 사용가능하게 할 경우, Hibernate는 콜렉션들을 미리-페치
+ 시킬 수 있다:
+
+
+
+
+ ...
+
+]]>
+
+
+ batch-size 8로서, Hibernate는 4개의 SELECT들에서 3, 3, 3, 1 개의 콜렉션들을 로드시킬 것이다.
+ 다시 그 속성의 값은 특정 Session 내에서 초기화 되지 않은 콜렉션들의 예상되는 개수에 의존한다.
+
+
+
+ 만일 당신이 항목들의 포개진 트리를 가질 경우, 예를 들어 전형적인 bill-of-materials 패턴인 경우, (비록
+ 내포된 set 또는 실체화된 경로(materialized path)가
+ 주로-읽기-트리들에 대해 더 좋은 옵션일 수 있을지라도) 콜렉션들에 대한 batch 페칭이 특히 유용하다.
+
+
+
+
+
+ subselect 페칭 사용하기
+
+
+ 만일 한 개의 lazy 콜렉션이나 단일 값 프락시가 페치되어야 한다면, Hibernate는 하나의 subselect 내에서 원래의
+ 질의를 다시 실행하여 그것들 모두를 로드시킨다. 이것은 조각난 로딩 없이 batch 페칭과 동일한 방식으로 동작한다.
+
+
+
+
+
+
+
+ lazy 프로퍼티 페칭 사용하기
+
+
+ Hibernate3은 개별적인 프로퍼티들에 대한 lazy 페칭을 지원한다. 이 최적화 기술은 또한 fetch groups
+ 으로 알려져 있다. 이것이 대개 마케팅 특징임을 노트하길 바란다. 왜냐하면 실제로 행 읽기를 최적화 시키는 것이 컬럼 읽기에 대한
+ 최적화 보다 훨씬 더 중요하기 때문이다. 하지만 리거시 테이블들이 수백 개의 컬럼들을 갖고 데이터 모형이 개선될 수 없을 때,
+ 오직 클래스의 몇몇 프로퍼티들을 로드시키는 것 만이 유용할 수도 있다.
+
+
+
+ lazy 프로퍼티 로딩을 이용가능하게 하려면, 당신의 특정 property 매핑들에 대해 lazy 속성을 설정하라:
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ Lazy property 로딩은 빌드 시 바이트코드 수단을 필요로 한다! 만일 당신의 영속 클래스들이 개선되지 않을 경우,
+ Hibernate는 조용하게 lazy 프로퍼티 설정들을 무시하고 즉각적인 페칭으로 후퇴할 것이다.
+
+
+
+ bytecode 수단으로, 다음 Ant 태스크를 사용하라:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ 불필요한 컬럼 읽기를 피하는 다른 (더 좋은?) 방법은 적어도 읽기 전용 트랜잭션의 경우에 HQL 질의 또는 Criteria 질의의
+ 투사(projection) 특징들을 사용하는 것이다. 이것은 빌드 시 바이트코드 처리에 대한 필요성을 피하게 해주고 확실히 선호되는
+ 해결책이다.
+
+
+
+ 당신은 HQL에서 fetch all properties를 사용하여 프로퍼티들에 대한 통상의 eager 페칭을
+ 강제시킬 수 있다.
+
+
+
+
+
+
+
+ 두번째 레벨 캐시
+
+
+ Hibernate Session은 영속 데이터에 대한 트랜잭션 레벨 캐시이다. class-by-class와
+ collection-by-collection 기반 위에 클러스터 또는 JVM-레벨(SessionFactory-레벨) 캐시를 구성하는
+ 것이 가능하다. 당신은 클러스터링 된 캐시 속에 플러그인 할 수도 있다. 주의하라. 캐시들은 (비록 그것들이 캐시된 데이터를 정기적으로
+ 만료되도록 구성되어 있을지라도) 또 다른 어플리케이션에 의해 영속 저장소에 대해 행해진 변경들을 결코 알지 못한다.
+
+
+
+ 디폴트로, Hibernate는 JVM-레벨의 캐싱에 EHCache를 사용한다. (JCS 지원은 이제 진부하게 되었고 Hibernate의 장래 버전에서
+ 제거될 것이다.) 당신은 hibernate.cache.provider_class 프로퍼티를 사용하여
+ org.hibernate.cache.CacheProvider를 구현하는 클래스의 이름을 지정함으로써 다른 구현을 선택할 수도
+ 있다.
+
+
+
+
+
+ Cache 매핑들
+
+
+ 클래스 또는 콜렉션 매핑의 <cache> 요소는 다음 형식을 갖는다:
+
+
+
+
+
+
+ ]]>
+
+
+
+ usage는 캐싱 방도를 지정한다:
+ transactional,
+ read-write,
+ nonstrict-read-write 또는
+ read-only
+
+
+
+
+
+
+ 다른 방법으로 (선호적으로?), 당신은 hibernate.cfg.xml 내에 <class-cache>와
+ <collection-cache> 요소들을 지정할 수도 있다.
+
+
+
+ usage 속성은 캐시 동시성 방도를 지정한다.
+
+
+
+
+
+ 방도: 읽기 전용
+
+
+ 당신의 어플리케이션이 영속 클래스의 인스턴스들을 읽어들일 필요가 있지만 결코 변경할 필요가 없을 경우에 read-only
+ 캐시가 사용될 수 있다. 이것은 가장 간단한 최상의 퍼포먼스를 위한 방도이다. 그것은 클러스터 내 사용에는 완벽하게 안전하다.
+
+
+
+
+ ....
+]]>
+
+
+
+
+
+ 방도: 읽기/쓰기
+
+
+ 어플리케이션이 데이터를 업데이트 할 필요가 있을 경우, read-write 캐시가 적절하다. 만일
+ 직렬화 가능한(serializable) 트랜잭션 격리 레벨이 필요한 경우에는 이 캐시 방도가 결코 사용되지 말아야 한다. 만일 캐시가 JTA
+ 환경에서 사용될 경우, 당신은 JTA TransactionManager를 얻는 방도를 명명하는
+ hibernate.transaction.manager_lookup_class 프로퍼티를 지정해야 한다. 다른 환경들에서,
+ 당신은Session.close() 또는 Session.disconnect()가 호출될 때
+ 트랜잭션이 완료되는 것을 확실히 해야 한다. 만일 당신이 클러스터 내에 이 방도를 사용하고자 원할 경우, 당신은 기본 캐시 구현이
+ 잠금을 지원하도록 하는 것을 확실히 해야 한다. 미리 만들어진 캐시 프로바이더들은 그렇게 행하지 않는다.
+
+
+
+
+ ....
+
+
+ ....
+
+]]>
+
+
+
+
+ 방도: 엄격하지 않은 읽기/쓰기
+
+
+ 만일 어플리케이션이 오직 데이터를 자주 업데이트할 필요가 있고(예를 들어, 만일 두 개의 트랜잭션들이 동시에 동일한 항목을 업데이트
+ 하려고 시도하는 정말 있음직하지 않은 경우) 그리고 엄격한 트랜잭션 격리가 필요하지 않은 경우, nonstrict-read-write
+ 캐시가 적절할 수 있다. 만일 그 캐시가 JTA 환경에서 사용될 경우, 당신은 hibernate.transaction.manager_lookup_class를
+ 지정해야 한다. 다른 환경들에서, 당신은 Session.close() 또는 Session.disconnect()가 호출될 때
+ 트랜잭션이 완료되도록 확실히 해야 한다.
+
+
+
+
+
+ 방도: transactional
+
+
+ transactional 캐시 방도는 JBoss TreeCache와 같은 전체 트랜잭션적인 캐시 프로바이더들에 대한
+ 지원을 제공한다. 그런 캐시는 오직 JTA 환경 내에서 사용될 수 있고 당신은
+ hibernate.transaction.manager_lookup_class를 지정해야 한다.
+
+
+
+
+
+ 캐시 프로바이더들 중 어느 것도 모든 캐시 동시성 방도들을 지원하지 않는다. 다음 테이블은 어느 프로바이더들이 어느 동시성 방도들과
+ 호환되는지를 보여준다.
+
+
+
+
+
+
+
+ 캐시들을 관리하기
+
+
+ 당신이 객체를 save(), update() 또는 saveOrUpdate()에
+ 전달할 때마다 그리고 당신이 load(), get(), list(),
+ iterate() 또는 scroll()을 사용하여 객체를 검색할 때마다, 그 객체는
+ Session의 내부 캐시에 추가된다.
+
+
+ flush()가 차후적으로 호출될 때, 그 객체의 상태는 데이터베이스와 동기화 될 것이다. 만일 당신이 이 동기화가
+ 발생되는 것을 원하지 않거나 만일 당신이 대량의 객체들을 처리 중이고 메모리를 효율적으로 관리할 필요가 있을 경우, evict()
+ 메소드는 first-level 캐시로부터 그 객체와 그것의 콜렉션들을 제거하는데 사용될 수 있다.
+
+
+
+
+
+ Session은 또한 인스턴스가 세션 캐시에 속하는지 여부를 결정하는데 contains()
+ 메소드를 제공한다.
+
+
+
+ 세션 캐시로부터 모든 객체들을 완전하게 퇴거시키기 위해, Session.clear()를 호출하라.
+
+
+
+ second-level 캐시의 경우, 하나의 인스턴스, 전체 클래스, 콜렉션 인스턴스 또는 전체 콜렉션 role의 캐시된 상태를 퇴거시키는
+ SessionFactory 상에 정의된 메소드들이 존재한다.
+
+
+
+
+
+ CacheMode는 특정 세션이 second-level 캐시와 어떻게 상호작용하는지를 제어한다
+
+
+
+
+
+ CacheMode.NORMAL - second-level 캐시로부터 아이템들을 읽어들이고 second-level 캐시로
+ 아이템들을 기록한다
+
+
+
+
+ CacheMode.GET - second-level 캐시로부터 아이템들을 읽어들이지만, 데이터를 업데이트할 때를 제외하면
+ second-level 캐시로 기록하지 않는다
+
+
+
+
+ CacheMode.PUT - 아이템들을 second-level 캐시에 기록하지만, second-level 캐시로부터 읽어들이지
+ 않는다
+
+
+
+
+ CacheMode.REFRESH - 아이템들을 second-level 캐시로기록하지만, second-level 캐시로부터
+ 읽어들이지 않고, 데이터베이스로부터 읽어들인 모든 아이템들에 대한 second-level 캐시의 갱신을 강제시켜,
+ hibernate.cache.use_minimal_puts의 효과를 무시한다
+
+
+
+
+
+ second-level 캐시 또는 질의 캐시 영역의 내용물을 브라우징하려면 Statistics API를 사용하라:
+
+
+
+
+
+ 당신은 통계를 이용 가능하게 하고, 선택적으로 Hibernate로 하여금 캐시 엔트리들을 보다 인간에게 이해가능한 형식으로 유지시키도록
+ 강제시키는 것이 필요할 것이다:
+
+
+
+
+
+
+
+ 질의 캐시
+
+
+ 질의 결과 셋들이 또한 캐시될 수도 있다. 이것은 동일한 파라미터들을 가지고 자주 실행되는 질의들에만 유용하다.
+ 질의 캐시를 사용하기 위해 당신은 먼저 그것을 이용 가능하도록 해야 한다:
+
+
+
+
+
+ 이 설정은 두 개의 새로운 캐시 영역들 - 캐시된 질의 결과 셋들을 보관하는 것
+ (org.hibernate.cache.StandardQueryCache), 질의 가능한 테이블들에 대한 가장
+ 최신 업데이트들에 대한 timestamp들을 보관하는 다른 것
+ (org.hibernate.cache.UpdateTimestampsCache)-의 생성을 강제한다 . 질의 캐시는
+ 결과 셋 내에 실제 엔티티들의 상태를 캐시시키지 않음을 노트하라; 그것은 오직 식별자 값들과 값 타입의 결과들
+ 만을 캐시시킨다. 따라서 질의 캐시는 항상 second-level 캐시와 함께 사용되어야 한다.
+
+
+
+ 대부분의 질의들은 캐싱으로부터 이점이 없기에, 디폴트로 질의들은 캐시되지 않는다. 캐싱을 이용 가능하도록 하려면,
+ Query.setCacheable(true)를 호출하라. 이 호출은 기존 캐시 결과들을 찾는 것을 질의에게
+ 허용해주거나 질의가 실행될 때 그것의 결과들을 캐시에 추가하는 것을 허용해준다.
+
+
+
+ 만일 당신이 질의 캐시 만료 정책들에 대한 세밀한 제어를 필요로 할 경우, 당신은
+ Query.setCacheRegion()을 호출함으로써 특별한 질의에 대해 명명되니 캐시 영역을
+ 지정할 수도 있다.
+
+
+
+
+
+ 만일 질의가 그것의 질의 캐시 영역의 갱신을 강제시켜야 하는 경우에, 당신은 Query.setCacheMode(CacheMode.REFRESH)를
+ 호출해야 한다. 이것은 기본 데이터가 별도의 프로세스를 통해 업데이트되었고(예를 들면, Hibernate를 통해 변경되지 않았고)
+ 특정 질의 결과 셋들을 선택적으로 갱신하는 것을 어플리케이션에게 허용해주는 경우들에서 특별히 유용하다. 이것은
+ SessionFactory.evictQueries()를 통해 질의 캐시 영역을 퇴거시키는 보다 효과적인 대안이다.
+
+
+
+
+
+ 콜렉션 퍼포먼스 이해하기
+
+
+ 우리는이미 콜렉션들에 관해 얘기하는데 꽤 많은 시간을 소요했다. 이 절에서 우리는 콜렉션들이 실행 시에 어떻게 행위하는지에 관한
+ 한 쌍의 쟁점들을 조명할 것이다.
+
+
+
+ 분류
+
+ Hibernate는 세 가지 기본적인 종류의 콜렉션들을 정의한다:
+
+
+
+ 값들을 가진 콜렉션들
+
+
+ one to many 연관들
+
+
+ many to many 연관들
+
+
+
+
+ 이 분류는 여러 가지 테이블과 foreign key 관계들을 구별짓지만 우리가 관계형 모형에 대해 알 필요가 있는 모든 것을 우리에게
+ 말해주지 않는다. 관계형 구조와 퍼포먼스 특징들을 완전하게 이해하기 위해, 우리는 또한 콜렉션 행들을 업데이트하거나 삭제하기
+ 위해 Hibernate에 의해 사용되는 프라이머리 키의 구조를 검토해야 한다. 이것은 다음 분류를 제안한다:
+
+
+
+
+ 인덱싱 된 콜렉션들
+
+
+ set들
+
+
+ bag들
+
+
+
+
+ 모든 인덱싱된 콜렉션들(map들, list들, array들)은 <key>와
+ <index> 컬럼들로 이루어진 프라이머리 키를 갖는다. 이 경우에 콜렉션 업데이트들은 대개
+ 극히 효율적이다 - Hibernate가 그것을 업데이트나 삭제를 시도할 때 프라이머리 키는 효율적으로 인덱싱될 수 있고 특정 행은
+ 효율적으로 위치지워질 수 있다.
+
+
+
+ Set들은 <key>와 요소 컬럼들로 구성된 프라이머리 키를 갖는다. 이것은 몇몇 유형의 콜렉션 요소,
+ 특히 composite 요소들 또는 대형 텍스트 또는 바이너리 필드들에 대해 덜 효율적일 수 있다; 데이터베이스는 복잡한 프라이머리
+ 키를 효율적으로 인덱싱하는 것이 불가능할 수도 있다. 반면에 one to many 또는 many to many 연관들의 경우, 특히 합성
+ 식별자들의 경우에는 효율적일 수 있을 것 같다.(부수-노트: 만일 당신이 당신을 위한 <set>의
+ 프라이머리 키를 실제로 생성시키기 위해 SchemaExport를 원한다면 당신은 모든 컬럼들을
+ not-null="true"로 선언해야 한다.)
+
+
+
+ <idbag> 매핑들은 대용 키를 정의하여서, 그것들은 항상 업데이트에 매우 효율적이다. 사실,
+ 그것들은 최상의 경우이다.
+
+
+
+ Bag들은 가장 나쁜 경우이다. 왜냐하면 하나의 bag은 중복 요소 값들을 허용하고 인덱스 컬럼을 갖지 않기 때문에, 프라이머리 키가
+ 정의될 수 없다. Hibernate는 중복 행들 사이를 구분 짓는 방법을 갖고 있지 않다. Hibernate는 그것이 변경될 때마다
+ (한 개의 DELETE로) 콜렉션을 완전하게 제거하고 다시 생성시킴으로써 이 문제를 해결한다. 이것은 매우 비효율적이다.
+
+
+
+ one-to-many 연관의 경우, "프라이머리 키"는 데이터베이스 테이블의 물리적인 프라이머리 키가 아닐 수도 있지만- 이 경우에서도
+ 위의 분류는 여전히 유용하다. (그것은 여전히 Hibernate가 콜렉션의 개별 행들을 어떻게 "위치지우는"지를 반영한다.)
+
+
+
+
+
+ List, map, idbag, set들은 update에 가장 효율적인 콜렉션들이다
+
+
+ 위의 논의에서, 인덱싱된 콜렉션들과 (대개) set들이 요소들을 추가하고, 제거하고 업데이트함에 있어 가장 효율적인 오퍼레이션을
+ 허용해준다.
+
+
+
+ 아마 인덱싱 된 콜렉션들이 many to many 연관들을 위한 또는 값들을 가진 콜렉션들을 위한 set들에 대해 갖고 있는 하나 이상의
+ 장점들이 존재한다. Set의 구조 때문에, Hibernate는 요소가 "변경"될 때 행을 UPDATE
+ 하지 않는다. Set에 대한 변경들은 항상 (개별 행들에 대한) INSERT와
+ DELETE를 통해 동작한다. 다시 이 검토는 one to many 연관들에 적용되지 않는다.
+
+
+
+ 배열들이 lazy 될 수 없음을 관찰 한 후에, 우리는 list들, map들, 그리고 idbag들이 단독이 아닌 set들을 가진 가장 퍼포먼스가
+ 좋은(non-inverse) 콜렉션 타입들임을 결론 지을 것이다. Set들은 Hibernate 어플리케이션들에서 가장 공통된 종류의 콜렉션이
+ 될 것이라 예상된다. 이것은 "set" 의미가 관계형 모형에서 가장 고유한 것이기 때문이다.
+
+
+
+ 하지만, 잘 설계된 Hibernate 도메인 모형들에서, 우리는 대개 대부분의 콜렉션들이 사실 inverse="true"를
+ 가진 one-to-many 연관들임을 보게 된다. 이들 연관들의 경우, 업데이트는 연관의 many-to-one 엔드에 의해 처리되고, 따라서
+ 콜렉션 업데이트 퍼포먼스에 대한 검토들은 단순히 적용되지 않는다.
+
+
+
+
+
+ Bag들과 list들은 가장 효율적인 inverse 콜렉션들이다
+
+
+ 단지 당신이 영원히 bag들을 버리기 전에, bag들(과 또한 list들)이 set들보다 훨씬 더 성능이 좋은 특별한 경우들이 존재한다.
+ inverse="true"를 가진 콜렉션들(예를 들어, 표준 양방향 one-to-many 관계 특질)의 경우, 우리는
+ bag 요소들을 초기화(페치) 시킬 필요 없이 bag 또는 list에 요소들을 추가시킬 수 있다! 이것은 Collection.add()
+ 또는 Collection.addAll()이 (Set과는 달리) 항상 bag 또는
+ List에 대해 true를 반환해야하기 때문이다. 이것은 훨씬 다음 공통적인 코드를 더 빠르게 만들 수 있다.
+
+
+
+
+
+
+
+ 원 샷 delete
+
+
+ 종종 콜렉션 요소들을 하나씩 삭제하는 것은 극히 비효율적일 수 있다! Hibernate는 완전하게 바보가 아니어서, 그것은 새로운 공백의
+ 콜렉션의 경우(예를 들어 당신이 list.clear()를 호출했을 경우)에 그것을 행하지 않을 것임을 알고 있다.
+ 이 경우에, Hibernate는 하나의 DELETE 명령을 내릴 것이고 우리는 모두 행했다!
+
+
+
+ 우리가 길이 20인 하나의 콜렉션에 한 개의 요소를 추가하고 그런 다음 두 개의 요소들을 제거한다고 가정하자. Hibernate는
+ (콜렉션이 bag가 아닌 한) 한 개의 INSERT 문장과 두 개의 DELETE 문장을 명령
+ 내릴 것이다. 이것은 확실히 마음에 든다.
+
+
+
+ 하지만, 우리가 두 개의 요소들을 남겨둔채 18 개의 요소들을 제거하고 나서 세 개의 새로운 요소들을 추가한다고 가정하자.
+ 두 가지 가능한 처리 방법들이 존재한다.
+
+
+
+
+ 하나씩 열 여덟 개의 행들을 삭제한 다음에 세 개의 행들을 삽입시킨다
+
+
+
+ (한 개의 SQL DELETE로)전체 콜렉션을 삭제하고 모든 다섯개의 현재 요소들을 (하나씩) insert 시킨다
+
+
+
+
+
+ Hibernate는 두 번째 옵션이 아마 이 경우에 더 빠르다는 점을 알 만큼 충분히 영리하지 않다.(그리고 Hibernate가 그렇게 영리해지는 것을 희망
+ 하는 것은 가능하지 않을 것이다; 그런 특징은 데이터베이스 트리거들 등을 혼동스럽게 할 수도 있다.)
+
+
+
+ 다행히, 당신은 원래의 콜렉션을 폐기시키고(예를 들어 참조 해제하고) 모든 현재 요소들을 가진 새로이 초기화된 콜렉션을
+ 반환함으로써 아무때든지 이 특징을 강제시킬 수 있다. 이것은 시간이 흐름에 따라 매우 유용하고 강력해질 수 있다.
+
+
+
+ 물론 단 한번의 삭제(one-shot-delete)는 inverse="true"로 매핑된 콜렉션들에 적용되지 않는다.
+
+
+
+
+
+
+
+ 퍼포먼스 모니터링하기
+
+
+ 최적화는 퍼포먼스 관련 숫자들에 대한 모니터링과 접근 없이는 많이 사용되지 않는다. Hibernate는 그것의 내부적인 오퍼레이션들에 대한
+ 전체 영역의 특징들을 제공한다. Hibernate에서 Statistics는 SessionFactory에 대해 이용 가능하다.
+
+
+
+ SessionFactory 모니터링 하기
+
+
+ 당신은 두 가지 방법들로 SessionFactory metrics에 접근할 수 있다. 당신의 첫 번째 옵션은
+ sessionFactory.getStatistics()를 호출하고 당신 스스로 Statistics를
+ 읽거나 디스플레이 하는 것이다.
+
+
+
+ 만일 당신이 StatisticsService MBean을 이용 가능하도록 할 경우 Hibernate는 또한 metrics를
+ 발표하는데 JMX를 사용할 수 있다. 당신은 모든 당신의SessionFactory에 대해 한 개의 MBean 또는
+ 팩토리 당 한 개를 이용 가능하게 할 수 있다. 최소한의 구성 예제들은 다음 코드를 보라:
+
+
+
+
+
+
+
+
+ TODO: 이것은 의미가 없다: 첫번째 경우에, 우리는 직접 MBean을 검색하고 사용한다.
+ 두 번째 경우에 우리는 JNDI 이름을 사용하기 전에 세션 팩토리가 보관하고 있는 JNDI 이름을 부여해야 한다.
+ hibernateStatsBean.setSessionFactoryJNDIName("my/JNDI/Name")을 사용하라.
+
+
+ 당신은 SessionFactory에 대한 모니터링을 (비)활성화 시킬 수 있다
+
+
+
+
+ 구성 시 : hibernate.generate_statistics, 디폴트는 false
+
+
+
+
+
+
+ 실행 시 : sf.getStatistics().setStatisticsEnabled(true) 또는
+ hibernateStatsBean.setStatisticsEnabled(true)
+
+
+
+
+
+ Statistics(통계량들)은 clear() 메소드를 사용하여 프로그래밍 방식으로 재설정 될 수 있다. 요약은
+ logSummary() 메소드를 사용하여 logger(info 레벨)에게 전송될 수 있다.
+
+
+
+
+
+ Metrics
+
+
+ Hibernate는 매우 기본적인 것에서부터 어떤 시나리오들에만 관련된 전문 정보에 이르는 많은 metrics를 제공한다.
+ 모든 이용 가능한 카운터들은 Statistics interface API에서 3개의 카테고리로 설명되어 있다:
+
+
+
+
+ 열려진 세션들의 개수, 검색된 JDBC 커넥션들의 개수 등과 같은 일반적인 Session 사용에
+ 관련된 metrics.
+
+
+
+
+ 전체적으로 엔티티들, 콜렉션들, 질의들, 그리고 캐시들에 관련된 metrics(전역 metrics로 알려져 있음),
+
+
+
+
+ 특정한 엔티티, 콜렉션, 질의 또는 캐시 영역에 관련된 상세 metrics.
+
+
+
+
+
+ 예를 들어 당신은 엔티티, 콜렉션, 질의들의 캐시 성공율 및 실패율, put(역자 주, 캐시 시도, putt) 비율, 콜렉션들과 질의들,
+ 그리고 평균 질의 요구 시간 등을 찾을 수 있다. 수 밀리초들가 자바에서 근사치에 종속됨을 의식하라. Hibernate는 JVM 정밀도에
+ 묶여 있고, 몇몇 플랫폼들에서 이것은 심지어 약 10초가 될 수도 있다.
+
+
+
+ 간단한 getter들은 (예를 들어 특정 엔티티, 콜렉션, 캐시 영역에 묶이지 않은) 전역 metrics에 접근하는데 사용된다. 당신은
+ 그것(특정 엔티티, 콜렉션, 또는 캐시 영역)의 이름을 통해, 그리고 질의들에 대한 그것의 HQL 또는 SQL 표현을 통해 특정 엔티티,
+ 콜렉션, 또는 캐시 영역의 metrics에 접근할수 있다. 추가 정보는 Statistics, EntityStatistics,
+ CollectionStatistics, SecondLevelCacheStatistics, 그리고
+ QueryStatistics를 참조하라. 다음 코드는 간단한 예제를 보여준다:
+
+
+
+
+
+ 모든 엔티티들, 콜렉션들, 콜렉션들,질의들 그리고 영역 캐시들에 대해 작업하기 위해, 당신은 다음 메소드들로서 엔티티들,
+ 콜렉션들, 질의들, 그리고 영역 캐시들에 대한 이름들의 목록을 검색할 수 있다: getQueries(),
+ getEntityNames(), getCollectionRoleNames(), 그리고
+ getSecondLevelCacheRegionNames().
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/reference/ko/modules/persistent_classes.xml b/reference/ko/modules/persistent_classes.xml
new file mode 100644
index 0000000000..61299b7071
--- /dev/null
+++ b/reference/ko/modules/persistent_classes.xml
@@ -0,0 +1,440 @@
+
+ 영속 클래스들
+
+
+ 영속 클래스들은 비지니스 문제의 엔티티들(예를 들어 E-Commerce 어플리케이션에서 고객이나 주문)을 구현하는
+ 어플리케이션 내의 클래스들이다. 영속 클래스들의 인스턴스들은 영속 상태에 있는 것으로 전혀 간주되지 않는다 -
+ 대신에 하나의 인스턴스는 transient 또는 detached 상태일 수 있다.
+
+
+
+ Hibernate는 이들 클래스들이 Plain Old Java Object (POJO) 프로그래밍 모형으로서 알려진, 몇몇 간단한
+ 규칙들을 따를 경우에 가장 잘 동작한다. 하지만 이들 규칙들 중 어떤 것도 어려운 사양들이 아니다. 진정 Hibernate3는
+ 당신의 영속 객체들의 특징에 대해 매우 적은 것을 가정한다. 당신은 다른 방법들로 도메인 모형을 표현할 수 있다 :
+ 예를 들어 Map 인스턴스의 트리들을 사용하기.
+
+
+
+ 간단한 POJO 예제
+
+
+ 대부분의 자바 어플리케이션들은 고양이과들을 표현하는 영속 클래스를 필요로 한다.
+
+
+
+
+
+ 준수할 네 개의 주요 규칙들이 다음에 있다:
+
+
+
+ 아규먼트 없는 생성자를 구현하라
+
+
+ Cat은 아규먼트 없는 생성자를 갖는다. 모든 영속 클래스들은 Hibernate는
+ Constructor.newInstance()를 사용하여 그것들을 초기화 시킬 수 있도록 디폴트 생성자
+ (public이 아닐 수 있다)를 가져야 한다. 우리는 Hibernate 내에서 런타임 프락시 생성을 위한 최소한의
+ 패키지 가시성(visibility)를 가진 디폴트 생성자를 가질 것을 강력하게 권장한다.
+
+
+
+
+ identifier 프로퍼티를 제공하라(옵션)
+
+
+ Cat은 id로 명명된 하나의 프로퍼티를 갖는다. 이 프로퍼티는
+ 데이터베이스 테이블의 프라이머리 키 컬럼으로 매핑된다. 이 프로퍼티는 어떤 것으로 명명될 수도 있고, 그것의 타입은
+ 임의의 원시 타입, 원시 "wrapper" 타입, java.lang.String 또는 java.util.Date일
+ 수 있다. (만일 당신의 리거시 데이터베이스 테이블이 composite 키들을 갖고 있다면, 당신은 이들 타입들을 가진
+ 사용자 정의 클래스를 사용할 수도 있다 - 나중에 composite 식별자들에 대한 절을 보라)
+
+
+
+ identifier 프로퍼티는 엄격하게 옵션이다. 당신은 그것을 생략할 수도 있고, Hibernate로 하여금 내부적으로
+ 객체 식별자들을 추적하도록 할 수 있다. 하지만 우리는 이것을 권장하지 않는다.
+
+
+
+ 사실, 어떤 기능은 identifier 프로퍼티를 선언하는 클래스들에 대해서만 이용 가능하다:
+
+
+
+
+
+ detached 객체들에 대한 Transitive reattachment(cascade update 또는 cascade merge)
+ -
+
+
+
+
+ Session.saveOrUpdate()
+
+
+
+
+ Session.merge()
+
+
+ 를 보라
+
+
+
+
+
+ 우리는 당신이 영속 클래스들에 대해 일관되게 명명된 identifier 프로퍼티들을 선언할 것을 권장한다. 게다가 우리는
+ 당신이 nullable 타입(예를 들어 non-primitive)을 사용할 것을 권장한다.
+
+
+
+
+ final이 아닌 클래스들을 선호하라(옵션)
+
+ Hibernate의 중심 특징인, 프락시(proxies)들은 final이 아닌 영속 클래스들 또는 모두
+ public 메소드들로 선언된 인터페이스의 구현인 영속 클래스들에 의존한다.
+
+
+ 당신은 Hibernate로 인터페이스를 구현하지 않은 final 클래스들을 영속화 시킬 수 있지만
+ 당신은 lazy 연관 페칭(lazy association fetching)에 대해 프락시들을 사용할 수 없을 것이다 -그것은 퍼포먼스
+ 튜닝을 위한 당신의 옵션들을 제한시킬 것이다.
+
+
+ 당신은 또한 non-final 클래스들 상에 public final 메소드들을 선언하는 것을 피해야 한다.
+ 만일 당신이 public final 메소드를 가진 클래스를 사용하고자 원할 경우, 당신은
+ lazy="false"를 설정함으로써 명시적으로 프락싱을 사용 불가능하도록 해야 한다.
+
+
+
+
+ 영속 필드들을 위한 accessor들과 mutator들을 선언하라(옵션)
+
+
+ Cat은 그것의 모든 영속 필드들에 대해 accessor 메소드들을 선언한다. 많은 다른 ORM 도구들은
+ 인스턴스 변수들을 직접 영속화 시킨다. 우리는 관계형 스키마와 클래스의 내부적인 데이터 구조들 사이에 간접적인 수단을
+ 제공하는 것이 더 좋다고 믿고 있다. 디폴트로 Hibernate는 자바빈즈 스타일 프로퍼티들을 영속화 시키고, getFoo,
+ isFoo와 setFoo 형식의 메소드 이름들을 인지한다. 당신은 진정으로
+ 특정 프로퍼티에 대한 직접적인 필드 접근으로 전환할 수도 있다.
+
+
+
+ 프로퍼티들은 public으로 선언될 필요가 없다 - Hibernate는 디폴트로
+ protected get/set 쌍 또는 private get/set
+ 쌍을 가진 프로퍼티를 영속화 시킬 수 있다.
+
+
+
+
+
+
+
+ 상속 구현하기
+
+
+ 서브클래스는 또한 첫 번째 규칙들과 두 번째 규칙들을 주시해야 한다. 그것은 슈퍼클래스 Cat으로부터
+ 그것의 identifier 프로퍼티를 상속받는다.
+
+
+
+
+
+
+ equals()와 hashCode() 구현하기
+
+
+ 만일 당신이
+
+
+
+
+ 하나의 Set 속에 영속 클래스들의 인스턴스들을 집어넣고자 의도하고
+ (many-valued 연관들에 대해 권장되는 방법)
+ 그리고
+
+
+
+
+ detached 인스턴스들의 reattachment(재첨부)를 사용하고자 의도하는
+
+
+
+
+ 경우에 당신은 equals()와 hashCode() 메소드들을 오버라이드 시켜야 한다.
+
+
+
+ Hibernate는 특정 session 범위 내에서만 persistent identity(데이터베이스 행)과 Java identity의 같음을 보장한다.
+ 따라서 우리가 다른 세션들에서 검색된 인스턴스들을 혼합시키자마자, 우리가 Set들에 대해 유의미하게
+ 만들고자 원할 경우, 우리는 equals()와 hashCode()를 구현해야 한다.
+
+
+
+ 가장 명백한 방법은 두 객체들의 identifier 값을 비교함으로써 equals()/hashCode()를
+ 구현하는 것이다. 만일 그 값이 동일하다면, 둘다 동일한 데이터베이스 행이어야 하고, 그러므로 그것들은 같다(둘다 하나의
+ Set에 추가되는 경우에, 우리는 Set 속에서 하나의 요소만을 갖게 될 것이다).
+ 불행하게도, 우리는 생성되는 식별자들을 갖는 그 접근법을 사용할 수 없다! Hibernate는 오직 식별자 값들을 영속화 되는 객체들에
+ 할당할 것이고, 새로이 생성된 인스턴스는 임의의 identifier 값을 갖지 않을 것이다! 만일 인스턴스가 저장되지 않고 현재 하나의
+ Set 속에 있을 경우에, 그것을 저장하는것은 하나의 식별자 값을 그 객체에게 할당할 것이다. 만일
+ equals()와 hashCode()가 그 식별자 값에 기초할 경우, hash 코드는
+ Set의 계약을 파기하여 변경될 것이다. 이 문제에 대한 전체 논의에 대해서는 Hibernate 웹 사이트를 보라.
+ 이것은 Hibernate 쟁점이 아닌, 객체 identity와 equality에 관한 통상의 자바 의미론임을 노트하라.
+
+
+
+ 우리는 Business key equality를 사용하여 equals()와 hashCode()를
+ 구현할 것 권장한다. Business key equality는 equals() 메소드가 비지니스 키, 즉 실세계에서 우리의 인스턴스를
+ 식별하게 될 키(natural 후보 키)를 형성하는 프로퍼티들만을 비교한다는 점을 의미한다 :
+
+
+
+
+
+ 하나의 비지니스 키는 데이터베이스 프라이머리 키 후보 만큼 견고하지 않아야 한다(를 보라).
+ 대개 변경할 수 없는 프로퍼티 또는 유일한(unique) 프로퍼티는 대개 비지니스 키에 대한 좋은 후보들이다.
+
+
+
+
+
+ 동적인 모형들
+
+
+ 다음 특징들은 현재 실험적으로 고려되고 있으며 장래에는 변경될 수 있음을 노트하라.
+
+
+
+ 영속 엔티티들은 반드시 실행시에 POJO 클래스들로 또는 자바빈즈 객체들로 표현되어야할 필요는 없다. Hibernate는
+ 또한 (실행 시에 Map들을 가진 Map들을 사용하여) 동적인 모형들을 지원하고
+ DOM4J 트리들로서 엔티티들에 대한 표현을 지원한다. 이 접근법으로, 당신은 영속 클래스들을 작성하지 않고, 오직 매핑 파일들
+ 만을 작성한다.
+
+
+
+ 디폴트로, Hibernate는 통산의 POJO 모드로 동작한다. 당신은 default_entity_mode 구성 옵션을
+ 사용하여 특별한 SessionFactory에 대해 디폴트 엔티티 표현 모드를 설정할 수 있다
+ (을 보라).
+
+
+
+ 다음 예제들은Map들을 사용하는 표현을 설명한다. 먼저 매핑 파일에서, entity-name은
+ 클래스 이름 대신에(또는 클래스 이름에 덧붙여) 선언되어야 한다:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ 심지어 비록 연관들이 대상(target) 클래스 이름들을 사용하여 선언될지라도, 연관들의 대상(target) 타입은 또한 POJO가 아닌
+ 동적인 엔티티일 수 있음을 노트하라.
+
+
+
+ SessionFactory에 대한 디폴트 엔티티 모드를 dynamic-map으로 설정한 후에,
+ 우리는 Map들을 가진 Map들에 대해 실행 시에 작업할 수 있다:
+
+
+
+
+
+ dynamic 매핑의 장점들은 엔티티 클래스 구현에 대한 필요 없이도 프로토타이핑을 위한 빠른 전환 시간이다. 하지만 당신은
+ 컴파일 시 타입 체킹을 잃고 실행 시에 많은 예외상황들을 다루게 될 것이다. Hibernate 매핑 덕분에,
+ 나중에 고유한 도메인 모형 구현을 상단에 추가하는 것이 허용되어서, 데이터베이스 스키마가 쉽게 정규화 되고 소리가 울려 퍼질 수 있다.
+
+
+
+ 엔티티 표현 모드들은 또한 하나의 단위 Session 기준에 대해 설정될 수 있다:
+
+
+
+
+
+
+ EntityMode를 사용하는 getSession()에 대한 호출은
+ SessionFactory가 아닌, Session API에 대한 것임을 노트하길 바란다.
+ 그 방법으로, 새로운 Session은 기본 JDBC 커넥션, 트랜잭션, 그리고 다른 컨텍스트 정보를 공유한다.
+ 이것은 당신이 두 번째 Session 상에서 flush()와 close()를
+ 호출하지 말아야 하고, 또한 트랜잭션 및 커넥션 핸들링을 주된 작업 단위에게 맡긴다는 점을 의미한다.
+
+
+
+ XML 표현 가용성들에 대한 추가 정보는 에서 찾을 수 있다.
+
+
+
+
+
+ TODO: property 패키지와 proxy 패키지 내에 user-extension 프레임웍을 문서화 할 것.
+
+
+
+
diff --git a/reference/ko/modules/query_criteria.xml b/reference/ko/modules/query_criteria.xml
new file mode 100644
index 0000000000..973b1cd457
--- /dev/null
+++ b/reference/ko/modules/query_criteria.xml
@@ -0,0 +1,419 @@
+
+ Criteria 질의들
+
+
+ Hibernate는 직관적인, 확장 가능한 criteria query API를 특징 짓는다.
+
+
+
+ Criteria 인스턴스 생성하기
+
+
+ org.hibernate.Criteria인터페이스는 특정 영속 클래스에 대한 질의를 표현한다.
+ Session은 Criteria 인스턴스들에 대한 팩토리이다.
+
+
+
+
+
+
+
+ 결과 셋 제한하기
+
+
+ 개별적인 질의 기준은 org.hibernate.criterion.Criterion 인터페이스의 인스턴스이다.
+ org.hibernate.criterion.Restrictions 클래스는 어떤 미리 만들어진 Criterion
+ 타입들을 얻는 팩토리 메소드들을 정의한다.
+
+
+
+
+
+ 제한들은 논리적으로 그룹지워질 수도 있다.
+
+
+
+
+
+
+
+ 미리 만들어진 criterion 타입들(Restrictions 서브클래스들)의 영역이 꽤 존재하지만, 특히 유용한 것은
+ 당신으로 하여금 SQL을 직접 지정하도록 해준다.
+
+
+
+
+
+ 질의된 엔티티의 행 alias에 의해 대체된 {alias} placeholder.
+
+
+
+ criterion을 얻는 대안적인 접근법은 Property 인스턴스로부터 그것을 얻는 것이다. 당신은
+ Property.forName()을 호출하여 Property를 생성시킬 수 있다.
+
+
+
+
+
+
+
+ 결과들을 순서지우기(ordering)
+
+
+ 당신은 org.hibernate.criterion.Order를 사용하여 결과들을 순서(ordering)지울 수 있다.
+
+
+
+
+
+
+
+
+
+ 연관들
+
+
+ 당신은 createCriteria()를 사용하여 연관들을 네비게이트함으로써 관계된 엔티티들에 대한 컨스트레인트들을
+ 쉽게 지정할 수 있다.
+
+
+
+
+
+ 두 번째 createCriteria()는 Criteria의 새로운 인스턴스를 반환하며, 그것은
+ kittens 콜렉션의 요소들을 참조한다는 점을 노트하라.
+
+
+
+ 다음 대체 형식은 어떤 환경들에서 유용하다.
+
+
+
+
+
+ (createAlias()는 Criteria의 새로운 인스턴스를 생성시키지 않는다.)
+
+
+
+ 앞의 두 개의 질의들에 의해 반환된 Cat 인스턴스들에 의해 보관된 kittens 콜렉션들은 criteria에 의해
+ 사전-필터링되지 않는다는 점을 노트하라! 만일 당신이 criteria(기준)과 일치하는 고양이 새끼들을
+ 단지 검색하고자 원할 경우, 당신은 returnMaps()를 사용해야 한다.
+
+
+
+
+
+
+
+ 동적인 연관 페칭
+
+
+ 당신은 setFetchMode()를 사용하여 실행 시에 연관 페칭 의미를 지정할 수 있다.
+
+
+
+
+
+ 이 질의는 outer 조인으로 mate와 kittens 모두를 페치할 것이다. 추가 정보는
+ 을 보라.
+
+
+
+
+
+ 예제 질의들
+
+
+ org.hibernate.criterion.Example 클래스는 주어진 인스턴스로부터 질의 기준(criterion)을 구조화
+ 시키는 것을 당신에게 허용해준다.
+
+
+
+
+
+ 버전 프로퍼티들, 식별자들, 연관관계들이 무시된다. 디폴트로 null 값 프로퍼티들이 제외된다.
+
+
+
+ 당신은 Example이 적용되는 방법을 조정할 수 있다.
+
+
+
+
+
+ 당신은 연관된 객체들에 대한 criteria(기준)을 위치지우는데 examples를 사용할 수 있다.
+
+
+
+
+
+
+
+ Projections, aggregation 그리고 grouping
+
+ org.hibernate.criterion.Projections 클래스는 Projection 인스턴스들에
+ 대한 팩토리이다. 우리는 setProjection()을 호출하여 하나의 질의에 projection(투사,투영)을 적용시킨다.
+
+
+
+
+
+
+
+ criteria 질의 내에서는 명시적인 "group by"가 필수적이지 않다. 어떤 projection 타입들은
+ grouping projections들이게끔 정의되고, 그것은 또한 SQL group by 절 속에
+ 나타난다.
+
+
+
+ alias는 선택적으로 projection에 할당될 수 있어서, 투사된(projected) 값은 제한(restriction)들 또는 ordering들 내에서
+ 참조될 수 있다. 다음은 이것을 행하는 두 개의 다른 방법들이다:
+
+
+
+
+
+
+
+ alias() 메소드와 as() 메소드는 또 다른 alias 된
+ Projection의 인스턴스 내에 하나의 projection 인스턴스를 간단하게 포장한다. 지름길로서,
+ 당신이 projection을 projection 리스트에 추가할 때 당신은 alias를 할당할 수 있다:
+
+
+
+
+
+
+
+ 당신은 또한 projection들을 표현하는데 Property.forName()을 사용할 수 있다:
+
+
+
+
+
+
+
+
+
+ Detached 질의들과 서브질의들
+
+ DetachedCriteria 클래스는 당신에게 세션 영역의 외부에서 질의를 생성시키도록 하고, 그런 다음 나중에
+ 어떤 임의의 Session을 사용하여 그것을 실행하도록 한다.
+
+
+
+
+
+ DetachedCriteria는 또한 서브질의를 표현하는데 사용된다. 서브질의들을 포함하는 Criterion 인스턴스들은
+ Subqueries 또는 Property를 통해 얻어질 수 있다.
+
+
+
+
+
+
+
+ 심지어 상관관계 지워진 서브질의들이 가능하다:
+
+
+
+
+
+
+
+
+
+
+ natural 식별자에 의한 질의들
+
+
+ 대부분의 질의들에서, criteria 질의들을 포함하여, 질의 캐시는 매우 효율적이지 않다. 왜냐하면 질의 캐시 비유효성이
+ 너무 자주 발생하기 때문이다. 하지만, 우리가 캐시 비유효성 알고리즘을 최적화 시킬 수 있는 한 가지 특별한 종류의 질의가
+ 존재한다: 상수 natural 키에 의한 룩업. 몇몇 어플리케이션들에서, 이런 종류의 질의가 자주 발생한다. criteria API는
+ 이 쓰임새를 위한 특별한 설비를 제공한다.
+
+
+
+ 첫번째로 당신은 <natural-id>를 사용하여 당신의 엔티티에 대한 natural 키를 매핑
+ 시켜야 하고, second-level 캐시 사용을 가능하게 해야 한다.
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ 이 기능은 가변성 있는 natural 키들을 가진 엔티티들의 용도로 고안되어 있지 않음을 노트하라.
+
+
+
+ 다음으로 , Hibernate 질의 캐시를 사용 가능하도록 하라.
+
+
+
+ 이제 Restrictions.naturalId()는 캐시 알고리즘을 보다 효율적으로 사용할 수 있도록 우리에게 허용해준다.
+
+
+
+
+
+
+
diff --git a/reference/ko/modules/query_hql.xml b/reference/ko/modules/query_hql.xml
new file mode 100644
index 0000000000..e92e7610a2
--- /dev/null
+++ b/reference/ko/modules/query_hql.xml
@@ -0,0 +1,1048 @@
+
+ HQL: Hibernate Query Language
+
+
+ Hibernate는 (아주 의도적으로) SQL과 매우 흡사하게 보이는 극히 강력한 질의 언어를 구비하고 있다. 그러나 그 구문에 의해 우롱당하지 말라;
+ HQL은 상속, 다형성 그리고 연관과 같은 개념들을 이해하여서, 전체적으로 객체 지향적이다.
+
+
+
+ 대소문자 구분
+
+
+ 질의들은 Java 클래스들과 프로퍼티들의 이름들을 제외하면 대소문자를 구분하지 않는다. 따라서 SeLeCT는
+ SELECT와 같고 SELECT와도 같지만 org.hibernate.eg.FOO는
+ org.hibernate.eg.Foo과 같지 않고 foo.barSet은
+ foo.BARSET과 같지 않다.
+
+
+
+ 이 매뉴얼은 소문자 HQL 키워드를 사용한다. 몇몇 사용자들은 보다 나은 가독성을 위해 대문자 키워드들을 가진 질의들을 찾지만, 우리는
+ 자바 코드 속에 삽입될 때 이 컨벤션이 추하다는 점을 발견한다.
+
+
+
+
+
+ from 절
+
+
+ 가장 간단한 가능한 Hibernate 질의는 다음 형식이다:
+
+
+
+
+
+ 이것은 eg.Cat 클래스의 모든 인스턴스들을 간단하게 반환한다. 우리는 대개 클래스 이름을 수식할 필요가 없다.
+ 왜냐하면, auto-import가 디폴트이기 때문이다. 따라서 우리는 대개 항상 단지 다음과 같이 작성한다:
+
+
+
+
+
+ 대개 당신은 한 개의 alias를 할당할 필요가 있을 것이다. 왜냐하면 당신은 질의의 다른 부분들에서
+ Cat을 참조하고자 원할 것이기 때문이다.
+
+
+
+
+
+ 이 질의는 alias cat을 Cat 인스턴스들에 할당하여서, 우리는 나중에 질의 속에서
+ 그 alias를 사용할 수 있을 것이다. as 키워드는 옵션이다; 우리는 또한 다음과 같이 작성할 수 있다:
+
+
+
+
+
+ 여러 개의 클래스들은 cartesian product(카티젼 곱) 또는 "크로스" 조인으로 귀결되어 나타날 수도 있다.
+
+
+
+
+
+
+ 로컬 변수들에 대한 Java 네이밍 표준들과 일치되게, 첫 소문자를 사용하여 질의 alias들을 명명하는 것은 좋은 습관으로 간주된다
+ (예를 들면 domesticCat).
+
+
+
+
+
+ 연관들과 조인들
+
+
+ 우리는 또한 join을 사용하여 , 연관된 엔티티들에 또는 값들을 가진 콜렉션의 요소들에도 alias들을 할당할 수도
+ 있다.
+
+
+
+
+
+
+
+
+
+ 지원되는 join 타입들은 ANSI SQL로부터 빌려왔다
+
+
+
+
+
+ inner join
+
+
+
+
+ left outer join
+
+
+
+
+ right outer join
+
+
+
+
+ full join (대개 유용하지 않음)
+
+
+
+
+
+ inner join, left outer join, 그리고 right outer join
+ 구조체들이 약칭될 수 있다.
+
+
+
+
+
+ 게다가, "fetch" join은 값들을 가진 콜렉션들이나 연관관계들이 한 개의 select를 사용하여, 그것들의 부모 객체들에 따라 초기화 되는
+ 것을 허용해준다. 이것은 콜렉션의 경우에 특히 유용하다. 그것은 연관관계들과 콜렉션들에 대한 매핑 파일의 outer join과 lazy 선언들을
+ 효율적으로 오버라이드 시킨다. 추가 정보는 을 보라.
+
+
+
+
+
+ fetch join은 대개 alias를 할당할 필요가 없다. 왜냐하면, 연관된 객체들이 where 절(또는 어떤 다른 절)
+ 속에 사용되지 않을 것이기 때문이다. 또한 연관된 객체들은 질의 결과들 속에 직접 반환되지 않는다. 대신 그것들은 부모 객체를 통해
+ 접근될 수 있다. 우리가 alias를 필요로 할 수 있는 유일한 이유는 더 많은 콜렉션들을 재귀적으로 조인 페칭시키는 경우이다:
+
+
+
+
+
+ 현재의 구현에서는 오직 한 개의 콜렉션 role 만이 질의 속에서 join 페치될 수 있음을 노트하라(하나 이상의 role은 대개 한 개의
+ cartesian product(카티젼 곱)으로 귀결될 것이다). 또한 fetch 구조체는 scroll()
+ 또는 iterate()를 사용하여 호출된 질의들 속에서 사용될 수 없음을 노트하라. 마지막으로
+ full join fetch와 right join fetch는 무의미함을 노트하라.
+
+ fetch 구조체는 scroll() 또는 iterate()를 사용하여
+ 호출된 질의들 속에서 사용될 수 없음을 노트하라. 또한 fetch는 setMaxResults()
+ 또는 setFirstResult()와 함께 사용될 수도 없다. 한 개의 질의 내에 하나 이상의 콜렉션을 조인 페칭시켜서
+ 카티젼 곱을 생성시키는 것이 가능하다. 다중 콜렉션 role들을 조인 페칭시키는 것은 때때로 bag 매핑들에 대해 예기치 않은 결과들을
+ 초래하므로, 당신이 이 경우에 당신의 질의들을 처방하는 방법에 대해 주의하라. 마지막으로 full join fetch와
+ right join fetch는 의미가 없다.
+
+
+
+ 만일 당신이 (바이트코드 방편으로) property-레벨 lazy 페칭을 사용할 경우, Hibernate로 하여금 fetch all properties를
+ 사용하여 (첫 번째 질의에서) lazy 프로퍼티들을 즉시 페치하도록 강제시키는 것이 가능하다.
+
+
+
+
+
+
+
+
+ select 절
+
+
+ select 절은 질의 결과 셋 속에 반환할 객체들과 프로퍼티들이 어느 것인지를 골라 내도록 강제한다. 다음을
+ 검토하자:
+
+
+
+
+
+ 질의는 다른 Cat들의 mate들을 select 할 것이다. 실제로 당신은 이 질의들을 다음과
+ 같이 보다 축약형으로 표현할수도 있다:
+
+
+
+
+
+ 질의들은 컴포넌트 타입의 프로퍼티들을 포함하는 임의의 값 타입의 프로퍼티들을 반환할 수도 있다:
+
+
+
+
+
+
+
+ Family 클래스가 적당한 생성자를 갖고 있음을 가정하면,
+ 질의들은 여러 객체들 그리고/또는 프로퍼티들을 Object[] 타입의 배열로서,
+
+
+
+
+
+ 또는 List로서,
+
+
+
+
+
+ 또는 실제 typesafe 자바 객체로서,
+
+
+
+
+
+ 반환할 수도 있다.
+
+
+
+ 당신은 as를 사용하여 select되는 표현식들에 alias들을 할당할 수 있다:
+
+
+
+
+
+ 다음은 select new map과 함께 사용될 때 가장 유용하다:
+
+
+
+
+
+ 이 질의는 select된 값들에 대한 alias로부터 한 개의 Map을 반환한다.
+
+
+
+
+
+ 집계 함수들
+
+
+ HQL 질의들은 프로퍼티들에 대한 집계(aggregate) 함수들의 결과들을 반환할수도 있다:
+
+
+
+
+
+
+
+ 지원되는 집계 함수들은 다음과 같다
+
+
+
+
+
+ avg(...), sum(...), min(...), max(...)
+
+
+
+
+ count(*)
+
+
+
+
+ count(...), count(distinct ...), count(all...)
+
+
+
+
+
+ 당신은 select 절 속에 산술 연산자들, 연결 연산자, 그리고 인지된 SQL 함수들을 사용할 수 있다:
+
+
+
+
+
+
+
+ distinct 키워드와 all all가 사용될 수 있고 SQL의 경우와 동일한 의미를 갖는다.
+
+
+
+
+
+
+
+ Polymorphic(다형성) 질의들
+
+
+ 다음과 같은 질의:
+
+
+
+
+
+ 은 Cat의 인스턴스들 뿐만 아니라, 또한 DomesticCat과 같은 서브클래스들 또한
+ 반환한다. Hibernate 질의들은 from 절 내에 임의의 자바 클래스나 인터페이스를
+ 명명할 수 있다. 질의는 그 클래스를 확장하거나 그 인터페이스를 구현하는 모든 영속 클래스들의 인스턴스들을 반환할 것이다. 다음 질의는
+ 모든 영속 객체들을 반환할 것이다:
+
+
+
+
+
+ 인터페이스 Named는 여러 가지 영속 클래스들에 의해 구현될 수도 있다:
+
+
+
+
+
+ 이들 마지막 두 개의 질의들은 하나 이상의 SQL SELECT를 필요로 할 것임을 노트하라. 이것은 order by
+ 절이 정확하게 전체 결과 셋을 순서지우지 않음을 의미한다.(그것은 또한 당신이 Query.scroll()을 사용하여
+ 이들 질의들을 호출할 수 없음을 의미한다).
+
+
+
+
+
+ where 절
+
+
+ where 절은 반환된 인스턴스들의 목록을 제한시키는 것을 당신에게 허용해준다. 만일 alias가 존재하지 않을 경우,
+ 당신은 이름에 의해 프로퍼티들을 참조할 수도 있다:
+
+
+
+
+
+ 만일 한 개의 alias가 존재할 경우, 하나의 수식어가 붙은 프로퍼티 이름을 사용하라:
+
+
+
+
+
+ 는 'Fritz'로 명명된 Cat의 인스턴스들을 반환한다.
+
+
+
+
+
+ 는 Foo의 startDate 프로퍼티와 동일한 date 프로퍼티를
+ 가진 bar의 인스턴스가 존재하는 Foo의 모든 인스턴스를 반환할 것이다. 합성 경로
+ 표현식들은 where 절을 매우 강력하게 만들어준다. 다음을 검토하자:
+
+
+
+
+
+ 이 질의는 테이블 (inner) join을 가진 SQL 질의로 번역된다. 만일 당신이 다음과 같은 어떤 것을 작성했다면
+
+
+
+
+
+ 당신은 SQL에서 네 개의 테이블 join들을 필요로 하는 하나의 질의로 끝낼 것이다.
+
+
+
+ = 연산자는 프로퍼티들 뿐만 아니라 또한 인스턴스들을 비교하는데 사용될 수 있다:
+
+
+
+
+
+
+
+ 특별한 프로퍼티(소문자) id는 객체의 유일 식별자를 참조하는데 사용될 수 있다.(당신은 또한 그것의 프로퍼티
+ 이름을 사용할 수도 있다.)
+
+
+
+
+
+ 두 번째 질의가 효율적이다. 테이블 join이 필요 없다!
+
+
+
+ composite identifier(합성 식별자)들의 프로퍼티들이 또한 사용될 수 있다. Person이
+ country와 medicareNumber로 구성된 composite identifier를 갖는다고
+ 가정하자.
+
+
+
+
+
+
+
+ 다시 한번, 두 번째 질의는 테이블 join을 필요로 하지 않는다.
+
+
+
+ 마찬가지로, 특별한 프로퍼티 class는 다형적인 영속성(polymorphic persistence)의 경우에 인스턴스의
+ 판별자(discriminator) 값에 액세스한다. where 절 속에 삽입된 Java 클래스 이름은 그것의 판별자(discriminator) 값으로
+ 변환될 것이다.
+
+
+
+
+
+ 당신은 또한 컴포넌트들 또는 composite 사용자 정의 타입들의 (그리고 컴포넌트들의 컴포넌트들, 기타의) 프로퍼티들을
+ 지정할 수도 있다. (컴포넌트의 프로퍼티와은 반대로) 컴포넌트 타입의 프로퍼티로 끝나는 경로-표현식을 사용하려고 결코 시도하지 말라.
+ 예를 들어, 만일 store.owner가 컴포넌트 address를 가진 엔티티일 경우
+
+
+
+
+
+ "임의의" 타입은 다음 방법으로 join을 표현하는 것을 우리에게 허용해주는, 특별한 프로퍼티들 id와
+ class를 갖는다(여기서 AuditLog.item은 <any>로
+ 매핑된 프로퍼티이다).
+
+
+
+
+
+ log.item.class와 payment.class는 위의 질의 내에서 완전히 다른 데이터베이스
+ 컬럼들의 값들을 참조할 것임을 노트하라.
+
+
+
+
+
+ 표현식들
+
+
+ where 절 속에 허용되는 표현식들은 당신이 SQL로 작성할 수 있는 대부분의 종류의 것들을 포함한다:
+
+
+
+
+
+ 산술 연산자들 +, -, *, /
+
+
+
+
+ 바이너리 비교 연산자들 =, >=, <=, <>, !=, like
+
+
+
+
+ 논리 연산들 and, or, not
+
+
+
+
+ 그룹핑을 나타내는 괄호들 ( ), indicating grouping
+
+
+
+
+ in,
+ not in,
+ between,
+ is null,
+ is not null,
+ is empty,
+ is not empty,
+ member of and
+ not member of
+
+
+
+
+ "간단한" 경우, case ... when ... then ... else ... end, 그리고
+ "검색인" 경우, case when ... then ... else ... end
+
+
+
+
+ 문자열 연결 ...||... or concat(...,...)
+
+
+
+
+ current_date(), current_time(),
+ current_timestamp()
+
+
+
+
+ second(...), minute(...),
+ hour(...), day(...),
+ month(...), year(...),
+
+
+
+
+ EJB-QL 3.0에 의해 정의된 임의의 함수 또는 오퍼레이터: substring(), trim(),
+ lower(), upper(), length(), locate(), abs(), sqrt(), bit_length(), mod()
+
+
+
+
+ coalesce() 그리고 nullif()
+
+
+
+
+ numeric 값들이나 temporal 값들을 가독성 있는 문자열로 변환시키는 str()
+
+
+
+
+ cast(... as ...), 여기서 두번 째 아규먼트는 Hibernate 타입의 이름이고,
+ ANSI cast()와 extract()가 기본 데이터베이스에 의해 지원될 경우에는
+ extract(... from ...)
+
+
+
+
+ sign(), trunc(), rtrim(),
+ sin()과 같이 임의의 데이터베이스-지원 SQL 스칼라 함수
+
+
+
+
+ JDBC IN 파라미터들 ?
+
+
+
+
+ 명명된 파라미터들 :name, :start_date, :x1
+
+
+
+
+ SQL 리터럴들 'foo', 69, '1970-01-01 10:00:01.0'
+
+
+
+
+ Java public static final 상수들. eg.Color.TABBY
+
+
+
+
+
+ in 과 between은 다음과 같이 사용될 수 있다:
+
+
+
+
+
+
+
+ 그리고 부정형들은 다음과 같이 작성될 수 있다
+
+
+
+
+
+
+
+ 마찬가지로, is null과 is not null은 null 값들을 테스트하는데 사용될 수 있다.
+
+
+
+ Boolean들은 Hibernate 구성 내에 HQL 질의 치환들을 선언함으로써 표현식들 내에 쉽게 사용될 수 있다:
+
+
+ true 1, false 0]]>
+
+
+ 이것은 키워드 true와 false 키워드들을 이 HQL로부터 번역된 SQL에서
+ 리터럴 1과 0으로 대체될 것이다:
+
+
+
+
+
+ 당신은 특별한 프로퍼티 size로서 또는 특별한 size() 함수로서 콜렉션의 사이즈를
+ 테스트할 수 있다.
+
+
+ 0]]>
+
+ 0]]>
+
+
+ 인덱싱된 콜렉션들에 대해, 당신은minindex와 maxindex 함수들을 사용하여
+ 최소 인덱스과 최대 인덱스를 참조할 수 있다. 유사하게 당신은 minelement와
+ maxelement 함수를 사용하여 기본 타입을 가진 콜렉션의 최소 요소 및 최대 요소를 참조할 수 있다.
+
+
+ current date]]>
+
+ 100]]>
+
+ 10000]]>
+
+
+ SQL 함수들 any, some, all, exists, in은 콜렉션의 요소 또는 인덱스 세트(elements
+ 함수와 indices 함수), 또는 서브질의의 결과를 전달했을 때 지원된다(아래를 보라).
+
+
+
+
+
+
+
+
+ all elements(p.scores)]]>
+
+
+
+
+ 이들 구조체들-size, elements, indices,
+ minindex, maxindex, minelement,
+ maxelement-는 Hibernate3에서 where 절 내에서만 사용될 것임을 노트하라.
+
+
+
+ 인덱싱 된 콜렉션들의 요소들(배열들, 리스트들, map들)은 인덱스에 의해 참조될 수 있다(where 절 안에서만):
+
+
+
+
+
+
+
+
+
+
+
+ [] 내부의 표현식은 산술 표현실일 수 있다.
+
+
+
+
+
+ HQL은 또한 one-to-many 연관 또는 값들을 가진 콜렉션의 요소들에 대해 미리 만들어진 index() 함수를
+ 제공한다.
+
+
+
+
+
+ 기본 데이터베이스에 의해 제공되는 Scalar SQL 함수들이 사용될 수도 있다
+
+
+
+
+
+ 당신이 아직 이 모든 것을 납득하지 못한다면, SQL 내에서 다음 질의가 가독성이 얼마나 많고 적은지를 생각해보라:
+
+
+
+
+
+ 힌트 : 다음과 같은 어떤 것
+
+
+
+
+
+
+
+ order by 절
+
+
+ 질의에 의해 반환된 리스트는 반환된 클래스 또는 컴포넌트들의 프로퍼티에 의해 순서(ordering)지워질 수 있다:
+
+
+
+
+
+ asc 옵션 또는 desc 옵션은 각각 오름차순 또는 내림차순 정렬을 나타낸다.
+
+
+
+
+ group by 절
+
+
+ aggregate 값들을 반환하는 질의는 반환된 클래스나 컴포넌트들의 프로퍼티에 의해 그룹지워질 수 있다:
+
+
+
+
+
+
+
+ 또한 having 절이 허용된다.
+
+
+
+
+
+ SQL 함수들과 집계 함수들이 기본 데이터베이스에 의해 지원될 경우(예를 들어 MySQL은 지원되지 않는다)
+ having 절과 order by 절 속에 허용된다.
+
+
+ 100
+order by count(kitten) asc, sum(kitten.weight) desc]]>
+
+
+ group by 절도 order by 절 어느 것도 산술 표현식들을 포함할 수 없다는 점을
+ 노트하라.
+
+
+
+
+
+ 서브질의들
+
+
+ subselect들을 지원하는 데이터베이스들의 경우, Hibernate는 질의들 내에 서브질의들을 지원한다. 서브질의는 괄호로 묶여져야
+ 한다(자주 SQL 집계함수 호출에 의해). 심지어 서로 상관된 서브질의들(외부 질의 내에서 alias를 참조하는 서브질의들)이 허용된다.
+
+
+ (
+ select avg(cat.weight) from DomesticCat cat
+)]]>
+
+
+
+
+
+
+
+
+ select 리스트 내에 있는 하나 이상의 표현식을 가진 서브질의들의 경우에 당신은 tuple 생성자를 사용할 수 있다:
+
+
+
+
+
+ (Oracle 또는 HSQL이 아닌) 몇몇 데이터베이스들 상에서, 당신은 다른 컨텍스트들 내에서, 예를 들면 component들이나 composite
+ 사용자 타입들을 질의할 때 tuple 생성자들을 사용할 수 있음을 노트하라:
+
+
+
+
+
+ 이것을 더 풀어쓰면 다음과 동일하다:
+
+
+
+
+
+ 당신이 이런 종류의 것을 행하는 것을 원하지 않을 수 있는 두 가지 좋은 이유들이 존재한다: 첫 번째로 데이터베이스 플랫폼들 사이에 완전하게
+ 이식성이 없다; 두 번째로 그 질의는 이제 매핑 문서 속에 있는 프로퍼티들의 순서에 의존한다.
+
+
+
+
+
+ HQL 예제들
+
+
+
+ Hibernate 질의들은 매우 강력하고 복잡할 수 있다. 사실, 질의 언어의 힘은 Hibernate의 주요 판매 포인트들 중 하나이다. 다음은
+ 내가 최근의 프로젝트에서 사용했던 질의들과 매우 유사한 몇몇 예제 질의들이다. 당신이 작성하게 될 대부분의 질의들은 이것들보다 훨씬
+ 간단하다는 점을 노트하라!
+
+
+
+ 다음 질의는 특정 고객에 대한 모든 지불되지 않은 주문들의 주문 id, 항목들의 개수, 그리고 주문의 전체 합계값 그리고 주어진
+ 최소 전체 합계를 전체 합계값에 따라 결과들을 순서지워서 반환한다. 가격 결정에 있어, 그것은 현재의 카타록을 사용한다.
+ 귀결되는 SQL 질의는 ORDER, ORDER_LINE, PRODUCT,
+ CATALOG, PRICE 테이블들에 대한 네 개의 inner 조인들과 한 개의(상관지워지지
+ 않은) subselect를 갖고 있다.
+
+
+ = all (
+ select cat.effectiveDate
+ from Catalog as cat
+ where cat.effectiveDate < sysdate
+ )
+group by order
+having sum(price.amount) > :minAmount
+order by sum(price.amount) desc]]>
+
+
+ 괴물 같은 것! 실제로 실 생활에서, 나는 서브질의들을 매우 좋아하지 않아서, 나의 질의는 실제로 다음과 같았다:
+
+
+ :minAmount
+order by sum(price.amount) desc]]>
+
+
+ 다음 질의는 현재 사용자에 의해 가장 최근의 상태 변경이 행해졌던 AWAITING_APPROVAL 상태에 있는 모든
+ 지불들을 제외한, 각각의 상태에 있는 지불들의 개수를 카운트 한다. 그것은 PAYMENT,
+ PAYMENT_STATUS, PAYMENT_STATUS_CHANGE 테이블들에 대한 두 개의 inner
+ 조인들과 하나의 상관관계 지워진 subselect를 가진 SQL 질의로 변환된다.
+
+
+ PaymentStatus.AWAITING_APPROVAL
+ or (
+ statusChange.timeStamp = (
+ select max(change.timeStamp)
+ from PaymentStatusChange change
+ where change.payment = payment
+ )
+ and statusChange.user <> :currentUser
+ )
+group by status.name, status.sortOrder
+order by status.sortOrder]]>
+
+
+ 만일 내가 statusChanges 콜렉션을 set가 아닌 list로 매핑했다면, 그 질의는 작성하기가 훨씬 더
+ 간단했을 것이다.
+
+
+ PaymentStatus.AWAITING_APPROVAL
+ or payment.statusChanges[ maxIndex(payment.statusChanges) ].user <> :currentUser
+group by status.name, status.sortOrder
+order by status.sortOrder]]>
+
+
+ 다음 질의는 현재의 사용자가 속해 있는 조직의 모든 계정들과 지불되지 않은 지불들을 반환하는데 MS SQL Server
+ isNull() 함수를 사용한다. 그것은 ACCOUNT, PAYMENT,
+ PAYMENT_STATUS, ACCOUNT_TYPE, ORGANIZATION,
+ ORG_USER 테이블들에 대한 세 개의 inner 조인들, 하나의 outer 조인, 그리고 하나의 subselect를 가진
+ 한 개의 SQL 질의로 번역된다.
+
+
+
+
+
+ 몇몇 데이터베이스들의 경우, 우리는 (상관관계 지워진) subselect를 없앨 필요가 있을 것이다.
+
+
+
+
+
+
+
+ 대량 UPDATE & DELETE 문장들
+
+
+ HQL은 이제 HQL에서 UPDATE 및 DELETE 문장들을 지원한다. 상세한 것은 를 보라.
+
+
+
+
+ 팁들 & 트릭들
+
+
+ 당신은 실제로 질의 결과들을 반환하지 않고서 그것들(질의 결과들)의 개수를 카운트할 수 있다:
+
+
+
+
+
+ 콜렉션의 크기에 따라 결과를 순서(ordering)지우려면, 다음 질의를 사용하라:
+
+
+
+
+
+ 만일 당신의 데이터베이스가 subselect들을 지원할 경우, 당신은 당신의 질의의 where 절 내에 selection 사이즈에 대한 조건을
+ 위치지울 수 있다:
+
+
+ = 1]]>
+
+
+ 만일 당신의 데이터베이스가 subselect를 지원하지 않을 경우, 다음 질의를 사용하라:
+
+
+ = 1]]>
+
+
+ 이 해결책이 inner 조인 때문에 0개의 메시지를 가진 User를 반환할 수 없으므로, 다음 형식이 또한 유용하다:
+
+
+
+
+
+ 하나의 JavaBean의 프로퍼티들은 명명된 질의 파라미터들에 바인드될 수 있다:
+
+
+
+
+
+ 콜렉션들은 필터를 가진 Query 인터페이스를 사용하여 쪼매김하는 것이 가능하다:
+
+
+
+
+
+ 콜렉션 요소들은 질의 필터를 사용하여 순서(ordering)지워지거나 그룹지워질 수 도 있다:
+
+
+
+
+
+ 당신은 콜렉션을 초기화 하지 않고서 그것(콜렉션)의 크기를 찾을 수 있다:
+
+
+
+
+
+
+
+
diff --git a/reference/ko/modules/query_sql.xml b/reference/ko/modules/query_sql.xml
new file mode 100644
index 0000000000..a07040422a
--- /dev/null
+++ b/reference/ko/modules/query_sql.xml
@@ -0,0 +1,457 @@
+
+ Native SQL
+
+
+ 당신은 또한 당신의 데이터베이스의 native SQL dialect로 질의들을 표현할 수도 있다. 당신이 오라클의 질의 힌트들 또는
+ CONNECT 키워드와 같은 데이터베이스 지정적인 특징들을 활용하고자 원할 경우에 이것이 유용하다.
+ 그것은 또한 직접적인 SQL/JDBC 기반의 어플리케이션으로부터 Hibernate로의 보다 명료한 이전 경로를 제공한다.
+
+
+
+ Hibernate3은 또한 모든 create, update, delete, load 오퍼레이션들에 대해 (내장 프로시저들을 포함하여) 손으로 작성된 SQL을
+ 지정하는 것을 당신에게 허용해준다.
+
+
+
+ native SQL Query 생성시키기
+
+
+ SQL 질의들은 SQLQuery 인터페이스를 통해 제어되고, 그것은
+ Session.createSQLQuery()를 호출하여 얻어진다.
+
+
+
+
+
+ 이 질의는 다음을 지정했다:
+
+
+
+
+
+ Hibernate가 컬럼 alias들을 도입하기 위한, placeholder를 가진, SQL 질의 문자열
+
+
+
+
+ 그 질의에 의해 반환된 엔티티와 그것의 SQL 테이블 alias
+
+
+
+
+
+ addEntity() 메소드는 SQL 테이블 alias들을 엔티티 클래스들과 연관지우고, 질의 결과 셋의 형태를 결정한다.
+
+
+
+ addJoin() 메소드는 다른 엔티티들과 콜렉션들에 대한 연관들을 로드시키는데 사용될 수 있다.
+
+
+
+
+
+ native SQL 질의는 간단한 스칼라 값을 반환하거나 스칼라들과 엔티티들의 조합을 반환할 수도 있다.
+
+
+
+
+
+
+
+
+ Alias 참조와 프로퍼티 참조
+
+
+ 위에서 사용된 {cat.*} 표기는 "모든 프로퍼티"에 대한 약어이다. 다른 방법으로, 당신은 명시적으로 컬럼들을
+ 리스트할 수 있지만, 심지어 이 경우 조차도 우리는 Hibernate로 하여금 각각의 프로퍼티에 대해 SQL 컬럼 alias들을 끼워넣도록 해야 한다.
+ 컬럼 alias에 대한 placeholder는 테이블 alias 수식어가 붙은 프로퍼티 이름이다. 다음 예제에서, 우리는 매핑 메타데이터에 선언된
+ 것에 대해 다른 테이블 (cat_log)로부터 Cat들을 검색한다. 우리는 심지어 우리가
+ 좋아할 경우 where 절 속에 프로퍼티 alias들을 사용할 수도 있음을 주목하라.
+
+
+ The {}-syntax is not required for named queries.
+ See
+
+
+
+
+
+ 노트: 만일 당신이 각각의 프로퍼티를 명시적으로 리스트할 경우, 당신은 그 클래스와
+ 그것의 서브클래스들의 모든 프로퍼티들을 포함해야 한다!
+
+
+
+
+
+ 명명된 SQL 질의들
+
+
+ 명명된 SQL 질의들은 HQL 질의와 동일한 방법으로 매핑 문서 속에 정의될 수 있고 정확하게 호출될 수도 있다. 이 경우에, 우리는
+ addEntity() 호출을 필요로 하지 않는다.
+
+
+
+
+ SELECT person.NAME AS {person.name},
+ person.AGE AS {person.age},
+ person.SEX AS {person.sex}
+ FROM PERSON person
+ WHERE person.NAME LIKE :namePattern
+]]>
+
+
+
+ The <return-join> and <load-collection>
+ elements are used to join associations and define queries which initialize collections,
+ respectively.
+
+
+
+
+
+ SELECT person.NAME AS {person.name},
+ person.AGE AS {person.age},
+ person.SEX AS {person.sex},
+ adddress.STREET AS {address.street},
+ adddress.CITY AS {address.city},
+ adddress.STATE AS {address.state},
+ adddress.ZIP AS {address.zip}
+ FROM PERSON person
+ JOIN ADDRESS adddress
+ ON person.ID = address.PERSON_ID AND address.TYPE='MAILING'
+ WHERE person.NAME LIKE :namePattern
+]]>
+
+
+
+ 명명된 SQL 질의는 스칼라 값을 반환할수도 있다. 당신은 <return-scalar> 요소를 사용하여
+ 컬럼 alias와 Hibernate 타입을 지정해야 한다:
+
+
+
+
+
+ SELECT p.NAME AS name,
+ p.AGE AS age,
+ FROM PERSON p WHERE p.NAME LIKE 'Hiber%'
+]]>
+
+
+ 명시적으로 column/alias 이름들을 지정하는데 return-property 사용하기
+
+
+ Hibernate로 하여금 그것 자신의 alias들을 끼워넣도록 하기 위해 {}-구문을 사용하는 것 대신에,
+ <return-property>로서 당신은 사용할 컬럼 alias들이 무엇인지를 Hibernate에게 명시적으로
+ 알려줄 수 있다.
+
+
+
+
+
+
+
+
+ SELECT person.NAME AS myName,
+ person.AGE AS myAge,
+ person.SEX AS mySex,
+ FROM PERSON person WHERE person.NAME LIKE :name
+
+]]>
+
+
+ <return-property>는 또한 다중 컬럼들에 대해 동작한다. 이것은 다중-컬럼 프로퍼티들에
+ 대한 fine grained 제어를 허용할 수 없는 {}-구문을 가진 제약을 해결해준다.
+
+
+
+
+
+
+
+
+
+
+ SELECT EMPLOYEE AS {emp.employee}, EMPLOYER AS {emp.employer},
+ STARTDATE AS {emp.startDate}, ENDDATE AS {emp.endDate},
+ REGIONCODE as {emp.regionCode}, EID AS {emp.id}, VALUE, CURRENCY
+ FROM EMPLOYMENT
+ WHERE EMPLOYER = :id AND ENDDATE IS NULL
+ ORDER BY STARTDATE ASC
+]]>
+
+
+ 이 예제에서 우리는 끼워넣기(injection)를 위해 {}-구문과 함께 <return-property>를
+ 사용했음을 주목하라. 사용자들이 컬럼과 프로퍼티들을 참조하고자 원하는 방법을 선택하는 것을 사용자들에게 허용해줌으로써.
+
+
+
+ 만일 당신의 매핑이 한 개의 판별자(discriminator )를 가질 경우 당신은 판별자 컬럼을 지정하는데
+ <return-discriminator>를 사용해야 한다.
+
+
+
+
+ 질의를 위한 내장 프로시저 사용하기
+
+
+ Hibernate 3은 내장 프로시저들을 통한 질의들에 대한 지원을 도입한다. 내장 프로시저들은 Hibernate와 동작하는 것이
+ 가능하도록 첫 번째 출력-파라미터로서 한 개의 결과셋을 반환해야 한다. Oracle9 이상의 버전에서 그런 내장 프로시저에
+ 대한 예제는 다음과 같다:
+
+
+
+
+ Hibernate에서 이 질의를 사용하기 위해 당신은 하나의 명명된 질의(a named query)를 통해 그것을 매핑할 필요가 있다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { ? = call selectAllEmployments() }
+]]>
+
+
+ 내장 프로시저들은 현재 스칼라들과 엔티티들 만을 반환함을 주목하라. <return-join>과
+ <load-collection>은 지원되지 않는다.
+
+
+
+ 내장 프로시저들을 사용하는 규칙들/제약들
+
+
+ Hibernate에서 내장 프로시저들을 사용하기 위해서 프로시저들은 다음 몇몇 규칙들을 따라야 한다. 만일 그것들이 그들 규칙들을
+ 따르지 않을 경우 그것들은 Hibernate와 함께 사용 불가능하다. 만일 당신이 여전히 이들 프로시저들을 사용하고자 원할 경우,
+ 당신은 session.connection()을 통해 그것들을 실행시켜야 한다. 데이터베이스 벤더들이 다른 내장
+ 프로시저 의미론/구문을 갖고 있기 때문에, 규칙들은 각각의 데이터베이스에 따라 차이가 난다.
+
+
+
+ 내장 프로시저 질의들은 setFirstResult()/setMaxResults()로서 쪽매김 될 수 없다.
+
+
+
+ Oracle의 경우 다음 규칙들이 적용된다:
+
+
+
+
+
+ 프로시저는 한 개의 결과 셋을 반환해야 한다. 이것은 Oracle 9 또는 10에서 한 개의 SYS_REFCURSOR를
+ 반환함으로써 행해진다. Oracle에서 당신은 한 개의 REF CURSOR 타입을 정의할 필요가 있다.
+
+
+
+
+ 권장되는 형식은 { ? = call procName(<parameters>) } 또는
+ { ? = call procName }이다.(이것은 Hibernate 규칙이라기 보다는 Oracle 규칙이다.)
+
+
+
+
+
+ Sybase 또는 MS SQL server의 경우 다음 규칙들이 적용된다:
+
+
+
+
+
+ 프로시저는 한 개의 결과 셋을 반환해야 한다. 이들 서버들이 여러 개의 결과셋들과 업데이트 카운트들을 반환 할수 있다/할 것이이므로,
+ Hibernate는 결과들을 반복 순환할 것이고 그것의 반환 값으로서 하나의 결과 셋인 첫 번째 결과를 취할 것이다. 그 밖의 모든 것은
+ 폐기될 것이다.
+
+
+
+
+ 만일 당신이 당신의 프로시저 내에 SET NOCOUNT ON을 이용 가능하게 할 수 있다면 그것은 아마
+ 보다 효율적이게 될 것이지만 이것은 필요 조건이 아니다.
+
+
+
+
+
+
+
+
+
+ create, update 그리고 delete를 위한 맞춤형 SQL
+
+
+ Hibernate3는 create, update, delete 오퍼레이션들을 위한 맞춤형 문장들을 사용할 수 있다. Hibernate에서 클래스와 콜렉션
+ 영속자들은 구성 시에 생성된 문자열들의 집합(insertsql, deletesql, updatesql 등)을 이미 포함하고 있다.
+ <sql-insert>, <sql-delete>,
+ <sql-update> 매핑 태그들은 이들 문자열들을 오버라이드 시킨다:
+
+
+
+
+
+
+
+ INSERT INTO PERSON (NAME, ID) VALUES ( UPPER(?), ? )
+ UPDATE PERSON SET NAME=UPPER(?) WHERE ID=?
+ DELETE FROM PERSON WHERE ID=?
+]]>
+
+
+ SQL이 당신의 데이터베이스 내에서 직접 실행되어서, 당신이 좋아하는 임의의 dialect를 사용하는 것이 자유롭다. 만일 당신이 데이터베이스
+ 지정적인 SQL을 사용할 경우 이것은 물론 당신의 매핑의 이식성을 감소시킬 것이다.
+
+
+
+ 만일 callable 속성이 설정되면 내장 프로시저들이 지원된다:
+
+
+
+
+
+
+
+ {call createPerson (?, ?)}
+ {? = call deletePerson (?)}
+ {? = call updatePerson (?, ?)}
+]]>
+
+
+ 위치 파라미터들은 Hibernate가 그것들을 기대하는 것과 같은 순서가 되어야 하므로, 위치 파라미터들의 순서는 현재 절대적으로 중요하다.
+
+
+
+ 당신은 org.hiberate.persister.entity 레벨로 디버그 로깅을 사용 가능하게 함으로써 예상된 순서를 볼 수
+ 있다. 이 레벨을 이용 가능하게 하면 Hibernate는 엔티티들을 생성시키고, 업데이트하고, 삭제하는데 사용되는 정적인 SQL을 출력할 것이다.
+ (예상되는 결과를 보려면, Hibernate 생성된 정적인 sql을 오버라이드 시키게 매핑 파일들 속에 당신의 맞춤형 SQL을 포함시키지 않도록 염두에
+ 두라.)
+
+
+
+ Hibernate가 문장의 성공을 위해 몇몇 실행 시 체크들을 행하므로, 내장 프로시저들은 대부분의 경우들(읽기:다른 경우들 보다 그것을 더 잘
+ 행한다)에서 insert되고/업데이트되고/삭제된 행들의 개수를 반환하는데 필요하다. Hibernate는 항상 CUD 오퍼레이션들에 대한 숫자
+ 출력 파라미터로서 첫 번째 문장 파라미터를 등록시킨다:
+
+
+
+
+
+
+
+
+ 로딩을 위한 맞춤형 SQL
+
+
+ 당신은 또한 엔티티 로딩을 위한 당신 자신의 SQL (또는 HQL)을 선언할 수도 있다:
+
+
+
+
+ SELECT NAME AS {pers.name}, ID AS {pers.id}
+ FROM PERSON
+ WHERE ID=?
+ FOR UPDATE
+]]>
+
+
+ 이것은 앞서 논의했듯이 단지 명명된 질의 선언이다. 당신은 class 매핑 속에 이 명명된 질의를 참조할 수 있다:
+
+
+
+
+
+
+
+
+]]>
+
+
+ 이것은 심지어 내장 프로시저들에 동작한다.
+
+
+
+ 당신은 콜렉션 로딩을 위한 한 개의 질의를 정의할 수도 있다:
+
+
+
+
+
+
+]]>
+
+
+
+ SELECT {emp.*}
+ FROM EMPLOYMENT emp
+ WHERE EMPLOYER = :id
+ ORDER BY STARTDATE ASC, EMPLOYEE ASC
+]]>
+
+
+ 당신은 심지어 조인 페칭에 의해 하나의 콜렉션을 로드시키는 하나의 엔티티를 정의할 수 있다:
+
+
+
+
+
+ SELECT NAME AS {pers.*}, {emp.*}
+ FROM PERSON pers
+ LEFT OUTER JOIN EMPLOYMENT emp
+ ON pers.ID = emp.PERSON_ID
+ WHERE ID=?
+]]>
+
+
+
+
\ No newline at end of file
diff --git a/reference/ko/modules/quickstart.xml b/reference/ko/modules/quickstart.xml
new file mode 100644
index 0000000000..d5f9871489
--- /dev/null
+++ b/reference/ko/modules/quickstart.xml
@@ -0,0 +1,572 @@
+
+ Tomcat으로 빠른 시작
+
+
+ Hibernate 시작하기
+
+
+ 이 튜토리얼은 웹 기반의 어플리케이션 용 Apache Tomcat 서블릿 컨테이너에 대한 Hibernate 3.0 셋업을
+ 설명한다(우리는 버전 4.1을 사용했다. 5.0에 대한 차이점들은 적을 것이다). Hibernate는 모든 주요 J2EE
+ 어플리케이션 서버들의 관리되는 환경에서 잘 동작하고, 또는 심지어 스탠드얼론 어플리케이션들에서도 잘 동작
+ 한다. 이 튜토리얼에 사용되는 데이터베이스 시스템은 PostgreSQL 7.4이고, 다른 데이터베이스에 대한 지원은
+ 단지 Hibernate SQL dialect 구성과 커넥션 프로퍼티들을 변경시키는 것에만 관계된다.
+
+
+
+ 먼저 우리는 모든 필수적인 라이브러리들을 Tomcat 설치 장소에 복사해야 한다. 우리는 이 튜토리얼을 위해 별도의
+ 웹 컨텍스트(webapps/quickstart)를 사용하며, 따라서 우리는 전역 라이브러리 검색 경로
+ (TOMCAT/common/lib)와 webapps/quickstart/WEB-INF/lib
+ (JAR 파일들의 경우)와 webapps/quickstart/WEB-INF/classes 내 에 있는 컨텍스트
+ 레벨에서 클래스로더 양자를 고려해야 한다. 우리는 두 개의 클래스로더 레벨들을 전역 classpath와 컨텍스트
+ classpath로서 언급한다.
+
+
+
+ 이제 라이브러리들을 두 개의 classpath들에 복사하라:
+
+
+
+
+
+ 데이터베이스 용 JDBC 드라이버를 전역 classpath로 복사하라. 이것은 Tomcat에 번들로구성된 DBCP 커넥션
+ 풀 소프트웨어에 필요하다. Hibernate는 데이터베이스 상에서 SQL을 실행시키는데 JDBC 커넥션들을 사용하므로,
+ 당신은 풀링된 JDBC 커넥션들을 제공해야 하거나, 직접 지원되는 풀들(C3P0, Proxool) 중 하나를 사용하기
+ 위해 Hibernate를 구성해야 한다. 이 튜토리얼을 위해, (PostgreSQL 7.4와 JDK 1.4용) pg74jdbc3.jar
+ 라이브러리를 전역 classloaders 경로로 복사하라. 만일 당신이 다른 데이터베이스를 사용하고자 원할 경우,
+ 간단하게 그것의 적절한 JDBC 드라이버를 복사하라.
+
+
+
+
+ 그 밖의 어떤 것을 Tomcat 내의 전역 클래스로더 경로에 복사하지 말라. 또는 당신은 Log4j, commons-logging
+ 그리고 다른 것들을 포함하는 여러 가지 도구들에 관련된 문제점들을 얻게 될 것이다. 각각의 웹 어플리케이션에 대해
+ 컨텍스트 classpath를 사용하라. 즉 라이브러리들을 WEB-INF/lib에 복사하고, 당신 자신의 클래스들과
+ 구성 파일들/프로퍼티 파일들을 WEB-INF/classes에 복사하라. 두 디렉토리들 양자는 디폴트로 컨텍스트
+ classpath 내에 있다.
+
+
+
+
+ Hibernate는 JAR 라이브러리로서 패키지화 되어 있다. hibernate3.jar 파일은 어플리케이션의 다른 클래스들과
+ 함께 컨텍스트 classpath 속에 복사되어야 한다. Hibernate는 실행 시에 어떤 제 3의 라이브러리들을 필요로하고,
+ 이것들은 lib/ 디렉토리 내의 Hibernate 배포본에 번들화되어 있다; 를
+ 보라. 필요한 제3의 라이브러리들을 컨텍스트 classpath로 복사하라.
+
+
+
+
+
+
+ Hibernate 제3의 라이브러리
+
+
+
+
+
+
+
+ 라이브러리
+
+
+ 설명
+
+
+
+
+
+
+ antlr (필수)
+
+
+ Hibernate는 질의 파서들을 산출하는데 ANTLR을 사용하고, 이 라이브러리는 또한
+ 실행 시에 필요하다.
+
+
+
+
+ dom4j (필수)
+
+
+ Hibernate는 XML 구성과 XML 매핑 메타데이터 파일들을 파싱하는데 dom4j를 사용
+ 한다.
+
+
+
+
+ CGLIB, asm (필수)
+
+
+ Hibernate는 (Java reflection과 결합하여) 런타임 시에 클래스들을 고양시키는데
+ 코드 생성 라이브러리를 사용한다.
+
+
+
+
+ Commons Collections, Commons Logging (필수)
+
+
+ Hibernate는 Apache Jakarta Commons 프로젝트로부터 다양한 유틸리티 라이브러리
+ 들을 사용한다.
+
+
+
+
+ EHCache (필수)
+
+
+ Hibernate는 second-level 캐시를 위한 다양한 캐시 프로바이더들을 사용할 수 있다.
+ 만일 구성에서 변하지 않을 경우 EHCache가 디폴트 캐시 프로바이더이다.
+
+
+
+
+ Log4j (옵션)
+
+
+ Hibernate는 기본 로깅 메커니즘으로서 Log4j를 사용할 수 있는, Commons Logging
+ API를 사용한다. 만일 Log4j 라이브러리가 컨텍스트 라이브러리 디렉토리 속에서 이용
+ 가능하다면, Commons Logging은 Log4j와 컨텍스트 classpath 내에 있는 log4j.properties
+ 구성을 사용할 것이다. Log4j에 대한 예제 properties 파일은 Hibernate 배포본에
+ 번들화 되어 있다. 따라서 당신이 이면에서 무엇이 진행되는 지을 보고자 원할 경우에 log4j.jar와
+ (src/에 있는) 구성 파일을 당신의 컨텍스트 classpath 속으로 복사하라.
+
+
+
+
+ 필수 여부?
+
+
+ Hibernate 배포본 내에 있는 lib/README.txt 파일을 살펴보라.
+ 이것은 Hibernate에 배포된 제 3의 라이브러리들의 최신 목록이다. 당신은 그곳에 열거된
+ 모든 필수 라이브러리들과 옵션 라이브러리들을 찾게 될 것이다(여기서 "빌드 시 필요함"은
+ 당신의 어플리케이션이 아니라 Hibernate에 대한 의미임을 노트하라).
+
+
+
+
+
+
+
+ 우리는 이제 Tomcat과 Hibernate 양자에서 데이터베이스 커넥션 풀링과 공유를 설정한다. 이것은 Tomcat이
+ (그것의 미리 빌드되어 있는 DBCP 풀링 특징을 사용하여) 풀링된 JDBC 커넥션들을 제공할 것이고, Hibernate가
+ JNDI를 통해 이들 커넥션들을 요청한다는 것을 의미한다. 달리 당신은 Hibernate로 하여금 커넥션 풀을 관리하도록
+ 할 수 있다. Tomcat은 그것의 커넥션 풀을 JNDI에 바인드 시킨다; 우리는 리소스 선언을 Tomcat 메인 구성 파일인
+ TOMCAT/conf/server.xml에 추가한다:
+
+
+
+
+
+
+ factory
+ org.apache.commons.dbcp.BasicDataSourceFactory
+
+
+
+
+ url
+ jdbc:postgresql://localhost/quickstart
+
+
+ driverClassNameorg.postgresql.Driver
+
+
+ username
+ quickstart
+
+
+ password
+ secret
+
+
+
+
+ maxWait
+ 3000
+
+
+ maxIdle
+ 100
+
+
+ maxActive
+ 10
+
+
+]]>
+
+
+ 우리가 이 예제에서 구성하는 컨텍스트는 quickstart로 명명되고, 그것의 베이스는
+ TOMCAT/webapp/quickstart 디렉토리이다. 임의의 서블릿들에 접근하기 위해,
+ (물론 당신의 web.xml 속에 매핑된 서블릿의 이름을 추가하여) 당신의 브라우저에서
+ http://localhost:8080/quickstart 경로를 호출하라. 당신은 또한 계속 진행하고
+ 이제 공백의 process() 메소드를 가진 간단한 서블릿을 생성시킬 수 있다.
+
+
+
+ Tomcat은 이제 java:comp/env/jdbc/quickstart로 JNDI을 통해 커넥션들을 제공한다.
+ 만일 당신이 실행 중인 커넥션 풀을 얻는 것에 문제가 있다면 Tomcat 문서를 참조하라. 당신이 JDBC 드라이버 예외상황
+ 메시지를 얻을 경우, 먼저 Hibernate 없이 JDBC 커넥션 풀을 셋업하라. Tomcat & JDBC 튜토리얼들은
+ 그 웹 서이트에서 이용 가능하다.
+
+
+
+ 당신의 다음 단계는 Hibernate를 구성하는 것이다. Hibernate는 그것이 JDBC 커넥션들을 얻는 방법을 알고 있어야 한다.
+ 우리는 Hibernate의 XML 기반 구성을 사용한다. properties 파일을 사용하는 다른 접근법은 거의 동일하지만 XML
+ 구문이 허용하는 몇몇 특징들을 누락하고 있다. XML 구성 파일은 hibernate.cfg.xml로서
+ 컨텍스트 classpath (WEB-INF/classes) 내에 위치해 있다:
+
+
+
+
+
+
+
+
+
+ java:comp/env/jdbc/quickstart
+ false
+ org.hibernate.dialect.PostgreSQLDialect
+
+
+
+
+
+
+]]>
+
+
+ 우리는 SQL 명령들에 대한 로깅을 사용하지 않고 Hibernate에게 사용되는 데이터베이스 SQL direct가 무엇인지
+ 그리고 (Tomcat 바인드된 풀의 JNDI 주소를 선언하여) JDBC 커넥션들을 얻는 곳을 알려준다. dialect는
+ 필수적인 설정이고, 데이터베이스들은 SQL "표준"에 대한 그것들의 해석을 달리한다. Hibernate는 차이점들을
+ 처리하고 모든 주요 상용 데이터베이스들 및 오픈 소스 데이터베이스들 용도의 direct들을 번들로 포함하고 있다.
+
+
+
+ SessionFactory는 단일 데이터저장소에 관한 개념이고, 여러 데이터베이스들은 여러
+ 개의 XML 구성 파일들을 생성시키고 당신의 어플리케이션 속에서 여러 개의 Configuration
+ 및 SessionFactory 객체들을 생성시켜서 사용될 수 있다.
+
+
+
+ hibernate.cfg.xml의 마지막 요소는 영속 클래스 Cat에 대한
+ Hibernate XML 매핑 파일의 이름으로써 Cat.hbm.xml을 선언한다. 이 파일은 데이터베이스
+ 테이블(또는 테이블들)로 POJO 클래스 Cat 을 매핑시키는 메타데이터를 포함한다. 우리는
+ 곧 그 파일로 되돌아 갈 것이다. 먼저 POJO 클래스를 작성하고 그런 다음 그것을 위한 매핑 메타데이터를 선언하자.
+
+
+
+
+
+ 첫 번째 영속 클래스
+
+
+ Hibernate는 영속 클래스들에 대한 Plain Old Java Objects (POJOs, 종종 Plain Ordinary Java Objects로
+ 명명된다) 프로그래밍 모형으로 가장 잘 동작한다. POJO는 공용으로 가시적인 인터페이스로부터 내부적인 표상을 은폐시켜,
+ getter와 setter 메소드들을 통해 접근가능한 클래스들의 프로퍼티들을 가진 자바빈과 꽤 유사하다(필요하다면 Hibernate는
+ 또한 필드들에 직접 접근할 수 있다):
+
+
+
+
+
+ Hibernate는 그것의 프로퍼티 타입들의 사용에 제약되지 않고, 자바 콜렉션 프레임웍에서의 클래스들을 포함하여, 모든
+ 자바 JDK 타입들과 (String, char와 Date
+ 같은) 원시타입들이 매핑될 수 있다. 당신은 그것을 값들로서, 값들을 가진 콜렉션들로서, 또는 다른 엔티티들에 대한
+ 연관들로서 매핑시킬 수 있다. id는 그 클래스의 데이터베이스 식별자(프라이머리 키)를 표현하는
+ 특별한 프로퍼티이고, 그것은 Cat과 같은 엔티티들에 대해 매우 권장된다. Hibernate는 내부적으로만
+ 식별자들을 사용할 수 있지만, 우리는 우리의 어플리케이션 아키텍처에서 어떤 유연성을 상실하게 될 것이다.
+
+
+
+ 특정 인터페이스는 영속 클래스들에 대해 구현되지 말아야 하거나 특정 루트 영속 클래스로부터 서브 클래스로 만들지 말아야 한다.
+ Hibernate는 또한 바이트 코드 처리와 같은, 어떤 빌드 시 처리를 필요로 하지 않고, 그것은 오직 자바 reflection과
+ (CGLIB를 통한) 런타임 클래스 고양에만 의존한다. 따라서 Hibernate에 대한 POJO 클래스의 어떤 의존성 없이도, 우리는
+ 그것을 데이터베이스 테이블로 매핑할 수 있다.
+
+
+
+
+
+ cat 매핑하기
+
+
+ Cat.hbm.xml 매핑파일은 객체/관계형 매핑에 필요한 메타데이터를 포함한다. 메타데이터는 영속
+ 클래스들의 선언과 데이터베이스 테이블들에 대한 (컬럼들과 다른 엔티티들에 대한 foreign 키 관계들에 대한) 프로퍼티들의
+ 매핑을 포함한다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ 모든 영속 클래스는 식별자 속성을 가져야 한다(실제로 value-타입의 클래스들에 의존하지 않는, 엔티티들을 표현하는 유일한
+ 클래스들은 엔티티을 가진 컴포넌트들로 매핑된다). 이 프로퍼티는 영속 객체들을 구별짓는데 사용된다: 만일
+ catA.getId().equals(catB.getId())가 true일 경우, 두 개의 cat들은 같고, 이 개념은
+ database identity로 명명된다. Hibernate는 (데이터베이스 시퀀스, hi/lo 식별자 테이블들,
+ 그리고 어플리케이션 할당 식별자들에 대한 native 생성기들을 포함하는) 다른 시나리오들에 대해 여러 가지 식별자 생성기들을
+ 번들로 갖고 있다. 우리는 UUID 생성기(데이터이스에 의해 생성된 정수 대용 키들이 선호될 것이므로, 테스트용으로만 권장됨)를
+ 사용하고 또한 Hibernate 생성된 식별자 값을 위한 CAT 테이블의 CAT_ID
+ 컬럼을 (테이블의 프라이머리 키로서) 지정한다.
+
+
+
+ Cat의 모든 다른 프로퍼티들은 동일한 테이블로 매핑된다. name 프로퍼티의 경우에,
+ 우리는 그것을 명시적인 데이터베이스 컬럼 선언으로 매핑시켰다. 데이터베이스 스키마가 Hibernate의 SchemaExport
+ 도구에 의해 매핑 선언으로부터 (SQL DDL 문장들로) 자동적으로 생성될 때 이것이 특별히 유용하다. 모든 다른 프로퍼티들은
+ Hibernate의 디폴트 설정들을 사용하여 매핑되고, 디폴트 설정들은 당신이 가장 많은 시간을 필요로 하는 것이다. 데이터베이스
+ 내의 테이블 CAT은 다음과 같다:
+
+
+
+
+
+ 당신은 이제 수작업으로 당신의 데이터베이스 내에 이 테이블을 생성시킬 것이고, 만일 당신이 hbm2ddl
+ 도구로 이 단계를 자동화 시키고자 원할 경우 를 읽어라. 이 도구는 테이블 정의, 맞춤형
+ 컬럼 타입 컨스트레인트들, 유일 컨스트레인트들과 인덱스들을 포함하는, 전체 SQL DDL을 생성시킬 수 있다.
+
+
+
+
+
+ cat들에 작업하기
+
+
+ 우리는 이제 Hibernate의 Session을 시작할 준비가 되어 있다. 그것은 persistence manager
+ (영속 관리자)이고, 우리는 데이터베이스로 Cat들을 저장하고 데이터베이스로부터
+ Cat들을 검색하는데 그것을 사용한다. 그러나 먼저 우리는 SessionFactory로부터
+ Session(Hibernate의 작업 단위)를 얻어야 한다:
+
+
+
+
+
+ configure() 호출은 hibernate.cfg.xml 구성 파일을 로드시키고
+ Configuration 인스턴스를 초기화 시킨다. 당신이 SessionFactory(불변적임)를 빌드하기
+ 이전에 당신은 Configuration에 접근함으로써 다른 프로퍼티들을
+ 설정할 수 있다(그리고 심지어 매핑 메타데이터를 변경시킬 수 있다). 우리는 어디서 SessionFactory를
+ 생성시키고 우리의 어플리케이션 속에서 어떻게 그것에 접근할 수 있나?
+
+
+
+ SessionFactory는 대개 오직 한번만, 예를 들어 대개 load-on-startup
+ 서블릿으로 시작 시에 빌드된다. 이것은 또한 당신이 당신의 서블릿들 내에 있는 인스턴스 변수 속에 그것을 유지하지 않을 것이지만
+ 어떤 다른 위치에 유지시킬 것임을 의미한다. 더구나 우리는 어떤 종류의 Singleton을 필요로 하며,
+ 따라서 우리는 어플리케이션 코드로 쉽게 SessionFactory에 액세스 할 수 있다. 다음에 보여진 접근법은
+ 두 문제 모두를 해결한다: 시작 구성과 SessionFactory에 대한 쉬운 접근.
+
+
+
+ 우리는 HibernateUtil helper 클래스를 구현한다:
+
+
+
+
+
+ 이 클래스는 static 초기자를 가진 SessionFactory를 처리할 뿐만 아니라 또한 현재의 쓰레드를
+ 위한 Session을 소유하는 ThreadLocal 변수를 갖는다. 이 helper를
+ 사용하려고 시도하기 전에 thread-local 변수에 대한 자바 개념을 이해해야 한다. 보다 복잡하고 강력한 HibernateUtil
+ 클래스는 http://caveatemptor.hibernate.org/의 CaveatEmptor에서 찾을 수 있다.
+
+
+
+ SessionFactory는 threadsafe이고, 많은 쓰레드들이 동시에 그것에 접근할 수 있고
+ Session들을 요청할 수 있다. 하나의 Session은 데이터베이스에 대해
+ 한 개의 단위 작업을 나타내는 non-threadsafe 객체이다. Session들은 SessionFactory
+ 로부터 열려지고 모든 작업이 완료될 때 닫혀진다. 당신의 서블릿의 process() 메소드 내에 있는
+ 예제는 다음과 같을 수 있다(예외상황 처리 없이):
+
+
+
+
+
+ 하나의 Session 내에서 모든 데이터베이스 오퍼레이션은 데이터베이스 오퍼레이션들(심지어 읽기 전용
+ 오퍼레이션들 조차도)을 격리시키는 하나의 트랜잭션 내부에서 발생한다. 우리는 기본 트랜잭션 방도(우리의 경우, JDBC
+ 트랜잭션들)로부터 추상화시키는데 Hibernates Transaction API 를 사용한다. 이것은 우리의
+ 코드가 임의의 변경들 없이도 (JTA를 사용하는) 컨테이너-관리되는 트랜잭션들에 배치되는 것을 허용해준다.
+
+
+
+ 당신이 원하는 만큼 당신이 HibernateUtil.currentSession();을 호출할 수 있고, 당신은
+ 이 쓰레드의 현재 Session을 항상 얻을 것임을 노트하라. 당신은 서블릿 코드 내에서든 또는 서블릿 필터
+ 내에서든 HTTP response가 전송되기 전에, 당신의 단위 작업이 완료된 후에 Session이 확실히
+ 닫혀지도록 해야 한다. 두 번째 옵션의 좋은 측면은 쉬운 lazy 초기화이다: 뷰가 렌더링 될 때 Session이
+ 여전히 열려져 있어서, Hibernate는 당신이 현재 객체 그래프를 네비게이트 하는 동안 초기화 되지 않은 객체들을 로드시킬 수 있다.
+
+
+
+ Hibernate는 데이터베이스로부터 객체들을 검색하는데 사용될 수 있는 다양한 메소드들을 갖고 있다. 가장 유연한 방법은 Hibernate
+ Query Language (HQL)을 사용하는 것이다. Hibernate Query Language (HQL)은 배우기가 쉽고 SQL에 대한 강력한 객체 지향
+ 확장이다:
+
+
+
+
+
+ Hibernate는 또한 type-safe 질의들을 공식화 시키는데 사용될 수 있는 객체-지향 query by criteria
+ API을 제공한다. 물론 Hibernate는 데이터베이스와의 모든 SQL 통신을 위해 PreparedStatement들과
+ 파라미터 바인딩을 사용한다. 당신은 또한 Hibernate 직접적인 SQL 질의 특징을 사용할 수도 있거나 드문 경우에
+ Session으로부터 plain JDBC 커넥션을 얻을 수도 있다.
+
+
+
+
+
+ 마지막으로
+
+
+ 우리는 이 작은 튜토리얼 내에서 단지 Hibernate의 표면을 훑기만 했다. 우리는 우리의 예제들 속에 어떤 서블릿 지정적 코드를
+ 포함하지 않음을 노트하라. 당신이 적합한지를 알려고 할 때 당신은 당신 자신의 서블릿을 생성시켜야 하고 Hibernate 코드를
+ 삽입해야 한다.
+
+
+
+ 데이터 접근 계층으로서 Hibernate는 당신의 어플리케이션에 강하게 통합됨을 염두에 두라. 대개 모든 다른 레이어들은 영속
+ 메커니즘에 의존했다. 당신은 이 설계의 함축을 확실히 이해하도록 하라.
+
+
+
+ 보다 복잡한 어플리케이션 예제는 http://caveatemptor.hibernate.org/ 를 보고 http://caveatemptor.hibernate.org/에
+ 있는 다른 튜토리얼들을 살펴보라.
+
+
+
+
+
diff --git a/reference/ko/modules/session_api.xml b/reference/ko/modules/session_api.xml
new file mode 100644
index 0000000000..57d25ce794
--- /dev/null
+++ b/reference/ko/modules/session_api.xml
@@ -0,0 +1,1115 @@
+
+ 객체들로 작업하기
+
+
+ Hibernate는 기본 데이터베이스 관리 시스템의 상세로부터 개발자들을 은폐시켜줄 뿐만 아니라, 또한 객체들에 대한
+ 상태 관리를 제공하는 하나의 완전한 객체/관계형 매핑 솔루션이다. 이것은 공통적인
+ JDBC/SQL 영속 계층들 내에서의 SQL 문장들에 대한 관리와는 반대로, 자바 어플리케이션들에서
+ 영속에 관한 매우 고유한 객체-지향적 관점이다.
+
+
+
+ 달리 말해, Hibernate 어플리케이션 개발자들은 그들의 객체들의 상태에 대해 항상 생각해야 하고,
+ SQL 문장들의 실행에 대해서는 필수적이지 않다. 이 부분은 Hibernate에 의해 처리되고 시스템의 퍼포먼스를 튜닝할 때
+ 어플리케이션 개발자와 유일하게 관련된다.
+
+
+
+ Hibernate 객체 상태들
+
+
+ Hibernate 다음 객체 상태들을 정의하고 지원한다:
+
+
+
+
+
+ Transient - 만일 객체가 new 연산자를 사용하여 방금 초기화 되었다면
+ 객체는 transient이고, 그것은 Hibernate Session과 연관되어 있지 않다. 그것은 데이터베이스
+ 내에서 영속 표상을 갖지 않고 식별자 값이 할당되지 않았다. 만일 어플리케이션이 더 이상 참조를 소유하지 않을 경우
+ transient 인스턴스들은 쓰레기 수집기에 의해 파괴될 것이다. 객체를 영속화 시키는데
+ (그리고 이 전이(transition)에 대해 실행될 필요가 있는 SQL 문장들을 Hibernate로 하여금 처리하도록 하는데)
+ Hibernate Session을 사용하라.
+
+
+
+
+ Persistent - 하나의 영속 인스턴스는 데이터베이스 내에서 하나의 표상을 갖고 하나의 식별자 값을
+ 갖는다. 그것은 방금 저장되었거나 로드되었을 수 있지만, 정의상 그것은 Session의 범위 내에 있다.
+ Hibernate는 영속 상태에서 객체에 대해 행해진 임의의 변경들을 검출해낼 것이고 단위 작업이 완료될 때 그 상태를 데이터베이스와
+ 동기화 시킬 것이다. 개발자들은 하나의 객체가 transient로 되어야 할 때 UPDATE 문장들이나
+ DELETE 문장들을 수작업으로 실행하지 않는다.
+
+
+
+
+ Detached - 하나의 detached 인스턴스는 영속화 되었지만, 그것의
+ Session이 닫혀진 객체이다. 물론 그 객체에 대한 참조는 여전히 유효하고,
+ 그 detached 인스턴스는 이 상태에서도 변경될 수도 있다. 하나의 detached 인스턴스는 나중에
+ 그것(과 모두 변경들)을 다시 영속화 시켜서 새로운 Session에 다시 첨부될 수 있다.
+ 이 특징은 사용자가 생각할 시간을 필요로 하는 장 기간 실행되는 작업 단위를 위한 프로그래밍 모형을 가능하게
+ 해준다. 우리는 그것들을 어플리케이션 트랜잭션들, 즉 사용자의 관점의 작업 단위라고
+ 부른다.
+
+
+
+
+
+ 이제 우리는 상태들과 상태 전이(transition)들(그리고 전이를 트리거 시키는 Hibernate 메소드들)을 상세하게 논의할 것이다.
+
+
+
+
+
+ 객체들을 영속화 시키기
+
+
+ 하나의 영속 클래스의 새로이 초기화 된 인스턴스들은 Hibernate에 의해 transient로 간주된다.
+ 우리는 그것을 세션과 연관지어서 transient 인스턴스를 영속화 시킬 수 있다:
+
+
+
+
+
+ 만일 Cat이 생성된 식별자를 가질 경우, save()가 호출될 때
+ 그 식별자가 생성되고 cat에 할당된다. 만일 Cat이 하나의
+ assigned 식별자나 하나의 composite key를 가질 경우, save()를
+ 호출하기 전에 그 식별자가cat 인스턴스에 할당될 것이다. 당신은 또한 EJB3 초기 드래프트에서
+ 정의된 의미로 save() 대신 persist()를 사용할 수도 있다.
+
+
+
+ 다른 방법으로, 당신은 save()의 오버로드된 버전을 사용하여 식별자를 할당할 수 있다.
+
+
+
+
+
+ 만일 당신이 영속화 시키는 객체가 연관된 객체들(예를 들면. 앞의 예제에 있는 kittens 콜렉션)을 갖고 있다면,
+ 당신이 하나의 foreign 키 컬럼에 대해 하나의 NOT NULL 컨스트레인트를 갖지 않는 한,
+ 이들 객체들은 당신이 좋아하는 임의의 순서로 영속화 되었을 수도 있다. foreign 키 컨스트레인트들을 위배하는 위험성이
+ 결코 존재하지 않는다. 하지만 당신이 잘못된 순서로 그 객체들을 save() 시킬 경우 당신은
+ NOT NULL 컨스트레인트를 위배할 수도 있다.
+
+
+
+ 당신이 연관된 객체들을 자동적으로 저장시키는데 Hibernate의 transitive persistence(전이 영속)
+ 특징을 사용하는 것을 매우 좋아할 것이므로 대개 당신은 이 상세를 내버려둔다. 그때 NOT NULL 컨스트레인트
+ 위배들이 발생되지 않을지라도 - Hibernate는 모든 것을 처리할 것이다. Transitive persistence(전이 영속)은 이 장에서
+ 후반부에서 논의된다.
+
+
+
+
+
+ 객체를 로드시키기
+
+
+ Session의 load() 메소드들은 만일 당신이 그것(영속 인스턴스)의 식별자들을
+ 이미 알고 있을 경우에 영속 인스턴스를 검색하는 방법을 당신에게 제공한다. load()는 하나의 클래스 객체를
+ 취하고 그 상태를 영속(persistent) 상태로 그 클래스의 새로이 초기화 된 인스턴스 속으로 로드시킬 것이다.
+
+
+
+
+
+
+
+ 다른 방법으로 당신은 주어진 인스턴스 속으로 상태를 로드시킬 수 있다:
+
+
+
+
+
+ 만일 일치하는 데이터베이스 행이 존재하지 않을 경우에 load()가 unrecoverable(복구 불가능한) 예외상황을
+ 던질 것임을 노트하라. 만일 클래스가 프락시를 갖도록 매핑된 경우, load()는 초기화 되지 않은 프락시를 단지
+ 반환하고 당신이 그 프락시의 메소드를 호출하기 전까지는 실제로 데이터베이스에 접속하지 않는다. 당신이 데이터베이스로부터
+ 객체에 대한 연관을 실제로 로드시키지 않고서 객체에 대한 연관을 생성시키고자 원할 경우에 이 특징이 매우 유용하다. 만일
+ batch-size가 class 매핑에 정의되는 경우 그것은 또한 다중 인스턴스들이 하나의 배치로서 로드되는 것을
+ 허용해준다.
+
+
+
+ 만일 당신이 하나의 일치하는 행이 존재하는지를 확신할 수 없을 경우, 당신은 get() 메소드를 사용해야 한다.
+ 그것(get() 메소드)는 데이터베이스에 즉시 접속하고 만일 일치하는 행이 없을 경우 null을 반환한다.
+
+
+
+
+
+ 당신은 하나의 LockMode를 사용하는, SELECT ... FOR UPDATE를 사용하여
+ 하나의 객체를 로드시킬 수도 있다. 추가 정보는 API 문서를 보라.
+
+
+
+
+
+ 어떤 연관된 인스턴스들이나 포함된 콜렉션들은 당신이 그 연관에 대한 케스케이드 스타일로서 lock 또는
+ all을 지정하도록 결정하지 않는 한, FOR UPDATE로 선택되지 않음을 노트하라.
+
+
+
+ refresh() 메소드를 사용하여, 아무때나 하나의 객체와 모든 그것의 콜렉션들을 다시 로드시키는 것이
+ 가능하다. 데이터베이스 트리거들이 그 객체의 프로퍼티들 중 어떤 것을 초기화 시키는데 사용될 때 이것이 유용하다.
+
+
+
+
+
+ 중요한 질문이 대개 이 지점에서 나타난다: Hibernate는 데이터베이로부터 그것을 얼마나 많이 로드시키고 그리고 얼마나 많은
+ SQL SELECT들이 그것을 사용할 것인가? 이것은 페칭 방도에 의존하고
+ 에 설명되어 있다.
+
+
+
+
+
+ 질의하기
+
+
+ 만일 당신이 당신이 찾고 있는 객체들에 대한 식별자들을 모를 경우, 당신은 하나의 질의를 필요로 한다. Hibernate는 사용이 쉽지만
+ 강력한 객체 지향 질의 언어(HQL)를 지원한다. 프로그램 상의 질의 생성을 위해, Hibernate는 정교한 Criteria 및 Example 질의
+ 특징(QBC와 QBE)를 지원한다. 당신은 또한 객체들로의 결과 셋 변환을 위한 선택적인 Hibernate의 지원으로, 당신의 데이터베이스의
+ native SQL 속에 당신의 질의를 표현할 수도 있다.
+
+
+
+ 질의들을 실행하기
+
+
+ HQL 질의와 native SQL 질의는 org.hibernate.Query의 인스턴스로 표현된다. 이 인터페이스는
+ 파라미터 바인딩, 결과셋 핸들링을 위한, 그리고 실제 질의의 실행을 위한 메소드들을 제공한다. 당신은 항상 현재
+ Session을 사용하여 하나의 Query를 얻는다:
+
+
+
+
+
+ 하나의 질의는 대개 list()를 호출하여 실행되고, 질의의 결과는 메모리 내에서 하나의 콜렉션 속으로
+ 전체적으로 로드될 것이다. 하나의 질의에 의해 검색된 엔티티 인스턴스들은 영속(persistent) 상태에 있다. 당신의 질의가
+ 하나의 객체를 오직 반환할 것임을 당신이 알고 있을 경우에 uniqueResult() 메소드는 단축을 제공한다.
+
+
+
+ 결과들을 반복하기
+
+
+ 종종, 당신은 iterate() 메소드를 사용하여 질의를 실행함으로써 더 나은 퍼포먼스를 성취하는
+ 것이 가능할 수 있다. 이것은 오직 대개 질의에 의해 반환되는 실제 엔티티 인스턴스들이 이미 세션 내에 있거나
+ second-level 캐시 내에 있을 것임을 당신이 예상하는 경우일 것이다. 만일 그것들이 이미 캐시되지 않았다면,
+ iterate()는 list() 보다 더 느릴 것이고 간단한 질의에 대해
+ 많은 데이터베이스 접속들을, 대개 오직 식별자들을 반환하는 초기 select에 대해 1번의 접속과
+ 실제 인스턴스들을 초기화 시키는 추가적인 select들에 대해 n 번의 접속을 필요로 할 수 있다.
+
+
+
+
+
+
+ 튜플들을 반환하는 질의들
+
+
+ Hibernate 질의들은 때때로 객체들의 튜플들을 반환하고, 그 경우에 각각의 튜플은 배열로서 반환된다:
+
+
+
+
+
+
+
+ 스칼라 결과들
+
+
+ 질의들은 select 절 내에 하나의 클래스에 대한 하나의 프로퍼티를 지정할 수 있다.
+ 그것들은 심지어 SQL 집계 함수들을 호출할 수도 있다. 프로퍼티들이나 aggregate들은
+ "스칼라" 결과들(그리고 영속 상태에 있는 엔티티들이 아닌 것으)로 간주된다.
+
+
+
+
+
+
+
+ 바인드 프라미터들
+
+
+ Query 상의 메소드들은 명명된 파라미터들 또는 JDBC-스타일의 ?
+ 파라미터들에 바인딩 값들을 제공한다. JDBC와는 대조적으로, Hibernate 숫자 파라미터들은 0에서
+ 시작된다. 명명된 파라미터들은 질의 문자열 속에서 :name 형식의 식별자들이다.
+ 명명된 파라미터들의 장점들은 다음과 같다:
+
+
+
+
+
+ 명명된 파라미터들은 그것들이 질의 문자열 내에 발생하는 순서에 관계없다
+
+
+
+
+ 그것들은 동일한 질의 내에서 여러 번 발생할 수 있다
+
+
+
+
+ 그것은 자기-설명적이다
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 쪽매김
+
+
+ 만일 당신이 당신의 결과 셋에 경계(당신이 검색하고자 원하는 최대 개수 그리고/또는 당신이 검색하고자 원하는 첫 번째 행)을
+ 지정할 필요가 있다면 당신은 Query 인터페이스의 메소드들을 사용해야 한다:
+
+
+
+
+
+ Hibernate는 이 limit 질의를 당신의 DBMS의 native SQL로 번역하는 방법을 알고 있다.
+
+
+
+
+
+ 스크롤 가능한 iteration
+
+
+ 당신의 JDBC 드라이버가 스크롤 가능한 ResultSet들을 지원할 경우,
+ Query 인터페이스는 ScrollableResults 객체를 얻는데
+ 사용될 수 있고, 그것은 질의 결과들에 대한 유연한 네비게이션을 허용해준다.
+
+
+ i++ ) && cats.next() ) pageOfCats.add( cats.get(1) );
+
+}
+cats.close()]]>
+
+
+ 열려진 데이터베이스 커넥션(과 커서)가 이 기능에 필요함을 노트하고, 만일 당신이 쪽매김 기능을 작동시킬 필요가 있다면
+ setMaxResult()/setFirstResult()를 사용하라.
+
+
+
+
+
+ 명명된 질의들을 구체화 시키기
+
+
+ 당신은 또한 매핑 문서 속에 명명된 질의들을 정의할 수 있다.(만일 당신의 질의가 마크업으로서 해석될 수 있는 문자들을
+ 포함할 경우에 CDATA 섹션을 사용하는 것을 기억하라))
+
+
+ ?
+] ]>]]>
+
+
+ 파라미터 바인딩과 실행은 프로그램 상으로 행해진다:
+
+
+
+
+
+ 실제 프로그램 코드는 사용되는 질의 언어에 독립적이고, 당신은 또한 메타데이터로 native SQL 질의들을 정의할 수도 있거나
+ 그것들을 매핑 파일들 속에 기존 질의들을 위치지움으로써 기존 질의들을 Hibernate로 이전시킬 수도 있음을 노트하라.
+
+
+
+
+
+
+
+ 콜렉션들을 필터링 하기
+
+ 콜렉션 필터는 영속 콜렉션 또는 배열에 적용될 수 있는 질의의 특별한 타입이다. 질의 문자열은
+ 현재의 콜렉션 요소를 의미하는 this를 참조할 수 있다.
+
+
+
+
+
+ 반환되는 콜렉션은 하나의 bag으로 간주되고, 그것은 주어진 콜렉션에 대한 사본이다. 원래의 콜렉션은 변경되지 않는다
+ (이것은 이름 "filter"의 의미와는 정반대이지만, 예상되는 행위와 일치된다).
+
+
+
+ 필터들은 from 절을 필요로 하지 않음을 관찰하라(필요할 경우에 필터들이 한 개의 from 절을 가질 수
+ 있을지라도). 필터들은 콜렉션 요소들 자체들을 반환하는 것으로 한정되지 않는다.
+
+
+
+
+
+ 심지어 하나의 공백의 필터 질의도 예를 들어 거대한 콜렉션 내에 있는 요소들의 부분집합들을 로드시키는데 유용하다:
+
+
+
+
+
+
+
+ Criteria 질의들
+
+
+ HQL은 극히 강력하지만 몇몇 개발자들은 질의 문자열들을 빌드하기 보다, 객체 지향 API를 사용하여 동적으로 질의들을 빌드시키는
+ 것을 선호한다. Hibernate는 이들 경우들을 위한 직관적인 Criteria query API를 제공한다:
+
+
+
+
+
+ Criteria와 연관된 Example API 는
+ 에서 상세하게 논의된다.
+
+
+
+
+
+ native SQL에서 질의들
+
+
+ 당신은 createSQLQuery()를 사용하여 SQL 속에 하나의 질의를 표현할 수 있고,
+ Hibernate로 하여금 결과 셋들로부터 객체들로의 매핑을 처리하도록 할수도 있다. 당신은 아무때나
+ session.connection()을 호출할 수 있고 직접 JDBC Connection을
+ 사용할 수 있음을 노트하라. 만일 당신이 Hibernate API를 사용하고자 선택한 경우에 , 당신은 SQL alias들을
+ 중괄호들 속에 포함시켜야 한다:
+
+
+
+
+
+
+
+ SQL 질의들은 Hibernate 질의들처럼 명명된 파라미터들과 위치 파라미터들을 포함할 수도 있다. SQL 질의들에 대한
+ 추가 정보는 에서 찾을 수 있다.
+
+
+
+
+
+
+
+ 영속 객체들을 변경하기
+
+
+ 트랜잭션 상의 영속 인스턴스들 (예를들면. Session에 의해 로드되고,
+ 저장되고, 생성되거나 질의된 객체들)은 어플리케이션에 의해 처리될 수 있고 영속 상태에 대한 임의의 변경들은
+ Session이 flush될 때 영속화 될 것이다(이 장의 뒷 부분에서 논의됨).
+ 당신의 변경들을 영속화 시키기 위해 (다른 용도를 가진 update()와 같은) 특별한 메소드를 호출할
+ 필요가 없다. 따라서 객체의 상태를 업데이트 시키는 가장 간단한 방법은 Session이 열려 있는 동안,
+ 그것을 load()시키고 나서, 그것을 직접 처리하는 것이다:
+
+
+
+
+
+ 때때로 이 프로그래밍 모형은 불충분하다. 왜냐하면 그것은 동일한 세션 내에서 (객체를 로드시키는) SQL
+ SELECT와 (그것의 업데이트된 상태를 영속화 시키는) SQL UPDATE
+ 양자를 필요로 할 것이기 때문이다. 그러므로 Hibernate는 detached 인스턴스들을 사용하는 대안적인 접근법을 제공한다.
+
+
+
+ Hibernate는 UPDATE 문장 또는 DELETE 문장의 직접적인 실행을 위한
+ 그것 자신의 API를 제공하지 않음을 노트하라. Hibernate는 하나의 상태 관리 서비스이고, 당신은 그것을
+ 사용할 문장들을 생각하지 말아야 한다. JDBC는 SQL 문장들을 실행시키는 완전한 API이고, 당신은
+ session.connection()을 호출하여 아무때나 한 개의 JDBC Connection을
+ 얻을 수 있다. 게다가 대량 오퍼레이션의 개념은 온라인 트랜잭션 처리-지향적인 어플리케이션들을 위한 객체/관계형 매핑과 충돌한다.
+ 하지만 Hibernate의 장래 버전들은 특별한 대용량의 오퍼레이션 기능들을 제공할 수도 있다. 몇몇 가능한 배치 오퍼레이션 트릭들에
+ 대해서는 을 보라.
+
+
+
+
+
+ detached 객체들을 변경시키기
+
+
+ 많은 어플리케이션들은 하나의 트랜잭션 내에서 하나의 객체를 검색하고, 처리를 위한 UI 계층으로 그것을 전송하고,
+ 그런 다음 새로운 트랜잭션 내에서 변경들을 저장할 필요가 있다. 고도의-동시성 환경에서 이런 종류의 접근법을 사용하는
+ 어플리케이션들은 대개 작업의 "긴" 단위를 확실히 격리시키기 위해 버전화 된 데이터를 사용한다.
+
+
+
+ Hibernate는 Session.update() 메소드 또는 Session.merge() 메소드를
+ 사용하여 detached 인스턴스들의 재첨부를 제공함으로써 이 모형을 지원한다:
+
+
+
+
+
+ 만일 catId 식별자를 가진 Cat이 secondSession에 의해
+ 이미 로드되었을 경우에 어플리케이션이 그것을 다시 재첨부하려고 시도할 때, 예외상황이 던져졌을 것이다.
+
+
+
+ 만일 그 세션이 동일한 식별자를 가진 영속 인스턴스를 이미 포함하지 않음을 당신이 확신하는 경우에는
+ update()를 사용하고, 만일 당신이 세션의 상태를 고려하지 않은채로 아무때나 당신의 변경을 병합시키고자
+ 원할 경우에는 merge()를 사용하라. 달리 말해, 당신의 detached 인스턴스들에 대한 재첨부가 실행되는
+ 첫 번째 오퍼레이션임을 확실히 함으로써, update()는 대개 갓 만들어진 세션에서 당신이 호출하게 될
+ 첫 번째 메소드이다.
+
+
+
+ 어플리케이션은 만일 그것이 detached 인스턴스들의 상태가 또한 업데이트 되는 것을 원할 경우에만
+ 주어진 detached 인스턴스로부터 도달 가능한 detached 인스턴스들을 개별적으로update() 시킬 것이다.
+ 이것은 물론 transitive persistence(전이 영속)을 사용하여 자동화 될 수 있고,
+ 를 보라.
+
+
+
+ lock() 메소드는 또한 하나의 객체를 새로운 세션에 대해 다시 연관시키는것을 어플리케이션에게 허용해준다.
+ 하지만 detached 인스턴스는 변경되지 않아야 한다!
+
+
+
+
+
+ lock()이 여러가지 LockMode들에 사용될 수 있음을 노트하고,
+ 상세한 것은 API 문서와 트랜잭션 처리에 관한 장을 보라. 재첨부는 lock()에 대한
+ 유일한 쓰임새는 아니다.
+
+
+
+ 긴 작업 단위에 대한 다른 모형들은 에서 논의된다.
+
+
+
+
+
+ 자동적인 상태 검출
+
+
+ Hibernate 사용자들은 새로운 식별자를 생성시켜서 transient 인스턴스를 저장하거나
+ 그것의 현재 식별자와 연관된 detached 인스턴스들을 업데이트/재첨부 시키는 일반적인 용도의 메소드를 요청했다.
+ saveOrUpdate() 메소드는 이 기능을 구현한다.
+
+
+
+
+
+ saveOrUpdate()의 사용 예제와 의미는 초심자들에게는 혼동스러워 보인다. 먼저, 하나의 세션에서 온
+ 인스턴스를 또 다른 새로운 세션 내에서 사용하려고 시도하지 않는 한, 당신은 update(),
+ saveOrUpdate(), 또는 merge()를 사용할 필요는 없을 것이다.
+ 몇몇 전체 어플리케이션들은 이들 메소드들 중 어느 것도 결코 사용하지 않을 것이다.
+
+
+
+ 대개 update() 또는 saveOrUpdate()는 다음 시나리오에서 사용된다:
+
+
+
+
+
+ 어플리케이션이 첫 번째 세션 내에 객체를 로드시킨다
+
+
+
+
+ 객체가 UI 티어로 전달된다
+
+
+
+
+ 몇몇 변경들이 그 객체에 행해진다
+
+
+
+
+ 객체가 비지니스 로직 티어로 전달된다
+
+
+
+
+ 어플리케이션은 두 번째 세션에서 update()를 호출함으로써 이들 변경들을 영속화 시킨다
+
+
+
+
+
+ saveOrUpdate()는 다음을 행한다:
+
+
+
+
+
+ 만일 객체가 이 세션 내에서 이미 영속화 되어 있을 경우, 아무것도 행하지 않는다
+
+
+
+
+ 만일 그 세션과 연관된 또 다른 객체가 동일한 식별자를 가질 경우, 예외상황을 던진다
+
+
+
+
+ 만일 그 객체가 식별자 프로퍼티를 갖지 않을 경우, 그것을 save() 시킨다
+
+
+
+
+ 만일 객체의 식별자가 새로이 초기화 된 객체에 할당된 값을 가질 경우, 그것을 save() 시킨다
+
+
+
+
+ 만일 객체가 (<version> 또는 <timestamp>에 의해)
+ 버전화 되고, version 프로퍼티 값이 새로이 초기화 된 객체에 할당된 것과 동일한 값일 경우, 그것을 save()
+ 시킨다
+
+
+
+
+ 그 밖의 경우 그 객체를 update() 시킨다
+
+
+
+
+
+ 그리고 merge()는 매우 다르다:
+
+
+
+
+
+ 만일 세션과 현재 연관된 동일한 식별자를 가진 영속 인스턴스가 존재할 경우,
+ 주어진 객체의 상태를 영속 인스턴스 상으로 복사한다
+
+
+
+
+ 만일 세션과 현재 연관된 영속 인스턴스가 존재하지 않을 경우, 데이터베이스로부터 그것을 로드시키려고 시도하거나
+ 새로운 영속 인스턴스를 생성시키려고 시도한다
+
+
+
+
+ 영속 인스턴스가 반환된다
+
+
+
+
+ 주어진 인스턴스는 세션과 연관되지 않고, 그것은 detached 상태에 머무른다
+
+
+
+
+
+
+
+ 영속 객체들을 삭제하기
+
+
+ Session.delete()는 데이터베이스로부터 객체의 상태를 제거할 것이다.
+ 물론 당신의 어플리케이션은 여전히 detached 객체에 대한 참조를 소유할 것이다. 영속 인스턴스를 transient로 만들 때
+ delete()를 생각하는 것이 최상이다.
+
+
+
+
+
+ 당신은 foreign 키 컨스트레인트 위배들에 대한 위험성 없이 당신이 좋아하는 어떤 순서로 객체들을 삭제할 수도 있다.
+ 잘못된 순서로 객체들을 삭제함으로써 foreign 키 컬럼에 대한 NOT NULL 컨스트레인트를 위배할 가능성이
+ 여전히 존재한다. 예를 들어, 당신이 부모를 삭제하지만, 그 자식들을 삭제하는 것을 잊은 경우.
+
+
+
+
+
+ 두 개의 다른 데이터저장소들 사이에 객체들을 복제하기
+
+
+ 영속 인스턴스들의 그래프를 취하고 식별자 값들을 다시 생성시키지 않고서 그것들을 다른 저장소 속에 영속화 시키는 것을 가능하도록
+ 만드는 것이 종종 유용하다.
+
+
+
+
+
+ ReplicationMode는 replicate()가 데이터베이스 내에 있는 기존의
+ 행들과의 충돌을 처리하게될 방법을 결정한다.
+
+
+
+
+
+ ReplicationMode.IGNORE - 동일한 식별자를 가진 기존 데이터베이스 행이 존재할
+ 경우에 그 객체를 무시한다
+
+
+
+
+ ReplicationMode.OVERWRITE - 동일한 식별자를 가진 어떤 기존의 데이터베이스 행을 덮어 쓴다
+
+
+
+
+ ReplicationMode.EXCEPTION - 만일 동일한 식별자를 가진 기존 데이터베이스 행이 존재할 경우에
+ 예외상황을 던진다
+
+
+
+
+ ReplicationMode.LATEST_VERSION - 행의 버전 번호가 객체의 버전 번호 보다 이전의 것이면 덮어쓰고,
+ 그 밖의 경우에 그 객체를 무시한다
+
+
+
+
+
+ 이 특징의 쓰임새들은 다른 데이터베이스 인스턴스들 속으로 입력된 데이터 일치시키기, 제품 업그레이드 동안에 시스템 구성 정보
+ 업데이트 하기, non-ACID 트랜잭션들 동안에 행해진 변경들을 롤백시키기 등을 포함한다.
+
+
+
+
+
+ Session을 flush 시키기
+
+
+ 시간이 지남에 따라 Session은 JDBC 커넥션의 상태와 메모리 내에 보관된 객체들의 상태를 동기화 시키는데
+ 필요한 SQL 문장들을 실행시킬 것이다. 이 프로세스 flush는 다음 시점들에서 디폴트로 발생한다
+
+
+
+
+
+ 몇몇 질의들이 실행되기 전에
+
+
+
+
+ org.hibernate.Transaction.commit() 시점에서
+
+
+
+
+ Session.flush() 시점에서
+
+
+
+
+
+ SQL 문장들이 다음 순서로 실행 명령이 내려진다
+
+
+
+
+
+
+ 대응하는 객체들이 Session.save()를 사용하여 저장되었던 것과 같은 순서로, 모든 엔티티 삽입들
+
+
+
+
+ 모든 엔티티 업데이트들
+
+
+
+
+ 모든 콜렉션 삭제들
+
+
+
+
+ 모든 콜렉션 요소 삭제들, 업데이트들 그리고 삽입들
+
+
+
+
+ 모든 콜렉션 삽입들
+
+
+
+
+ 대응하는 객체들이 Session.delete()를 사용하여 삭제되었던 것과 같은 순서로 모든 엔티티 삭제들.
+
+
+
+
+
+ (한가지 예외는 객체들이 저장될 때 native ID 생성을 사용하는 객체들이 insert 되는 점이다.)
+
+
+
+ 당신이 명시적으로 flush() 시킬 때를 제외하면, Session이 JDBC 호출들을
+ 실행시키는 시점, 그것들이 실행되는 순서만을 절대적으로 보장하지는 않는다.
+ 하지만 Hibernate는 Query.list(..)가 실효성이 없는 데이터를 결코 반환하지 않을 것임을 보장하거나;
+ 그것들이 잘못된 데이터도 반환하지 않을 것임을 보장한다.
+
+
+
+ flush가 너무 자주 발생하지 않도록 디폴트 행위를 변경하는 것이 가능하다. FlushMode 클래스는 세 개의
+ 다른 모드들을 정의한다: 오직 커밋 시(그리고 Hibernate Transaction API가 사용될 때에만) flush 모드,
+ 설명된 루틴을 사용하는 자동적인 flush 모드, 또는 flush()가 명시적으로 호출되지 않는 한 flush 시키지
+ 않는 모드. 마지막 모드는 오래 동안 실행되는 작업 단위에 대해 유용하고, 여기서 Session은 열려진채로
+ 유지되고 오랜 시간 동안 연결이 해제된 채로 유지된다. (를 보라).
+
+
+
+
+
+ flush 동안에, 하나의 예외상황이 발생할 수도 있다(예를 들면. 만일 DML 오퍼레이션이 컨스트레인트를 위반할 경우). 예외상황들을
+ 처리하는 것은 Hibernatem의 트랜잭션 특징에 관한 어떤 이해를 수반하며, 우리는 에서 그것을
+ 논의한다.
+
+
+
+
+
+ Transitive persistence(전이 영속)
+
+
+ 특히 당신이 연관된 객체들의 그래프를 다룰 경우에, 특히 개별 객체들을 저장하고, 삭제하거나, 재첨부시키는 것이 꽤 번거롭다.
+ 공통된 경우는 하나의 부모/자식 관계이다. 다음 예제를 검토하자:
+
+
+
+ 만일 부모/자식 관계에서 자식들이 값(value) 타입(예를 들면. 주소들 또는 문자열들을 가진 하나의 콜렉션)일 경우, 그것들의 생명주기는
+ 부모에 의존할 것이고 상태 변경들에 대해 편리한 "케스케이딩"에 더 이상의 액션이 필요하지 않을 것이다. 만일 부모가 저장될 때,
+ 값(value)-타입의 자식 객체들도 마찬가지로 저장되고, 부모가 삭제될 때, 자식들이 삭제될 것이다. 이것은 심지어 콜렉션으로부터 하나의
+ 자식을 제거하는 그런 오퍼레이션들에 대해서도 동작한다; Hibernate는 이것을 검출하고, 값(value)-타입의 객체들은 참조를 공유할 수
+ 없으므로, 데이터베이스로부터 그 자식을 삭제시킨다.
+
+
+
+ 이제 값(value) 타입이 아닌, 엔티티들인 부모와 자식 객체들을 가진 동일한 시나리오를 검토하자(예를 들면. 카테고리들과 아이템들,
+ 또는 부모 고양이나 자식 고양이). 엔티티들은 그것들 자신의 생명주기를 갖고, 공유된 참조들을 지원하고 (따라서 콜렉션으로부터 하나의
+ 엔티티를 제거하는 것은 그것이 삭제될 수 있음을 의미하지 않는다), 그리고 디폴트로 하나의 엔티티로부터 어떤 다른 연관된 엔티티들로의
+ 상태의 케스케이딩은 존재하지 않는다. Hibernate는 디폴트로 도달가능성에 의한 영속성(persistence by reachability)을
+ 구현하지 않는다.
+
+
+
+ - persist(), merge(), saveOrUpdate(), delete(), lock(), refresh(), evict(), replicate()를
+ 포함하는- Hibernate 세션에 대한 각각의 기본 오퍼레이션에 대해서 하나의 대응하는 케스케이딩 스타일이 존재한다. 케스케이드 스타일들
+ 각각은 create, merge, save-update, delete, lock, refresh, evict, replicate로 명명된다.
+ 만일 당신이 하나의 오퍼레이션이 하나의 연관에 따라 케스케이딩되는 것을 원할 경우, 당신은 매핑 문서 내에 그것을 지시해야 한다.
+ 예를 들면:
+
+
+ ]]>
+
+
+ 케스케이딩 스타일들이 결합될 수도 있다:
+
+
+ ]]>
+
+
+ 당신은 모든 오퍼레이션들이 그 연관에 따라 케스케이드 되어야 함을 지정하는데
+ cascade="all"을 사용할 수도 있다. 디폴트cascade="none"은 오퍼레이션들이
+ 케스케이드 되지 않을 것임을 지정한다.
+
+
+
+ 특정한 케스케이드 스타일인, delete-orphan은 오직 one-to-many 연관들에만 적용되고,
+ delete() 오퍼레이션이 그 연관으로부터 제거되는 임의의 자식 객체에 적용되어야 함을 나타낸다.
+
+
+
+
+ 권장사항들 :
+
+
+
+
+
+ 하나의 <many-to-one> 또는 <many-to-many> 연관에
+ 대해 케스케이드를 가능하게 하는 것은 대개 의미가 없다. 케스케이드는 <one-to-one> 연관과
+ <one-to-many> 연관에 대해 종종 유용하다.
+
+
+
+
+ 만일 자식 객체의 수명이 그 부모 객체의 수명에 묶여져 있을 경우, cascade="all,delete-orphan"을
+ 지정함으로써 그것을 생명 주기 객체로 만들어라.
+
+
+
+
+ 그 밖의 경우, 당신은 케스케이드를 전혀 필요로 하지 않을 수 있다. 그러나 만일 당신이 동일한 트랜잭션 내에서 부모와 자식에
+ 대해 자주 함께 작업하게 될 것이라 생각되고, 당신 스스로 타이핑 하는 것을 절약하고자 원할 경우,
+ cascade="persist,merge,save-update"를 사용하는 것을 고려하라.
+
+
+
+
+
+ cascade="all"을 가진 (단일 값 연관이든 하나의 콜렉션이든) 하나의 연관을 매핑시키는 것은
+ 그 연관을 부모의 저장/업데이트/삭제가 자식 또는 자식들의 저장/업데이트/삭제로 귀결되는 부모/자식
+ 스타일의 관계로 마크한다.
+
+
+ 게다가, 하나의 영속 부모로부터 하나의 자식에 대한 단순한 참조는 자식의 저장/업데이트로 귀결될 것이다. 하지만 이 메타포는 불완전하다.
+ 그것의 부모에 의해 참조 해제되는 자식은 cascade="delete-orphan"으로 매핑된 하나의
+ <one-to-many> 연관의 경우를 제외하면, 자동적으로 삭제되지 않는다.
+ 하나의 부모/자식 관계에 대한 케스케이딩 오퍼레이션의 정확한 의미는 다음과 같다:
+
+
+
+
+
+ 만일 부모가 persist()에 전달될 경우, 모든 자식들이 persist()에 전달된다
+
+
+
+
+ 만일 부모가 merge()에 전달될 경우, 모든 자식들이 merge()에 전달된다
+
+
+
+
+ 만일 부모가 save(), update() 또는 saveOrUpdate()에
+ 전달될 경우, 모든 자식들이 saveOrUpdate()에 전달된다
+
+
+
+
+ 만일 transient 또는 detached 자식이 영속 부모에 의해 참조될 경우, 그것은 saveOrUpdate()에 전달된다
+
+
+
+
+ 만일 부모가 삭제될 경우, 모든 자식들이 delete()에 전달된다
+
+
+
+
+ 만일 자식이 영속 부모에 의해 참조 해제 될 경우, cascade="delete-orphan"이 아닌 한,
+ 특별한 어떤 것도 발생하지 않는다 - 어플리케이션은 필요한 경우에 자식을 명시적으로 삭제해야 한다 -,
+ cascade="delete-orphan"인 경우에 "orphaned(고아)"인 경우 자식이 삭제된다.
+
+
+
+
+
+
+
+ 메타데이터 사용하기
+
+
+ Hibernate는 모든 엔티티와 값(value) 타입들을 가진 매우 풍부한 메타-레벨 모형을 필요로 한다. 시간이 지남에 따라, 이 모형은
+ 어플리케이션 그 자체에 매우 유용하다. 예를 들어, 어플리케이션은 어느 객체들이 복사되어야 하는지(예를 들면 가변적인 값(value) 타입들)
+ 그리고 어느 것이 복사되지 말아야 하는지(예를 들면, 불변의 value 타입들과 가능한 연관된 엔티티들)를 인지하는 "스마트" deep-copy
+ 알고리즘을 구현하는데 Hibernate의 메타데이터를 사용할 수도 있다.
+
+
+ Hibernate는 ClassMetadata 인터페이스와 CollectionMetadata 인터페이스
+ 그리고 Type 계층구조를 통해 메타데이터를 노출시킨다. 메타데이터 인터페이스들의 인스턴스들은
+ SessionFactory로부터 얻어질 수도 있다.
+
+
+
+
+
+
+
+
diff --git a/reference/ko/modules/toolset_guide.xml b/reference/ko/modules/toolset_guide.xml
new file mode 100644
index 0000000000..e234ab2591
--- /dev/null
+++ b/reference/ko/modules/toolset_guide.xml
@@ -0,0 +1,444 @@
+
+ 도구셋 안내
+
+
+ Hibernate에 대한 라운드트립 엔지니어링은 Eclipse 플러그인 세트, 명령라인 도구들, 뿐만 아니라 Ant 태스크들을 사용하여 가능하다.
+
+
+
+ Hibernate 도구들은 현재 기존 데이터베이스들에 대한 리버스 엔지니어링을 위해 Ant 태스크들 뿐만 아니라
+ Eclipse IDE용 플러그인들을 포함하고 있다:
+
+
+
+
+ 매핑 편집기: 자동 완성 기능과 구문 강조를 지원하는 Hibernate XML 매핑 파일들에 대한 편집기. 그것은 또한
+ 통상의 XML 편집기 보다 훨씬 더 융통성 있게 만들어서 클래스 이름들과 프로퍼티/필드 이름들에 대한 의미론적 자동 완성 기능을 지원한다.
+
+
+ 콘솔: 콘솔은 Eclipse에서 새로운 뷰이다. 당신의 콘솔 구성들에 대한 tree overview에 덧붙여, 당신은 또한
+ 당신의 영속 클래스들과 그것들의 관계들에 대한 상호작용 뷰를 얻는다. 콘솔은 당신의 데이터베이스에 대해 HQL 질의들을 실행하고 그 결과를
+ Eclipse 내에서 직접 브라우징 하도록 당신에게 허용해준다.
+
+
+ 개발 마법사들: 몇몇 마법사들이 Hibernate Eclipse 도구들에 제공된다; 당신은 Hibernate 구성
+ (cfg.xml) 파일들을 빠르게 생성시키는데 마법사를 사용하거나, 심지어 당신은 기존 데이터베이스 스키마를 POJO 소스 파일들과
+ Hibernate 매핑 파일들로 완전하게 리버스 엔지니어링할 수도 있다. 리버스 엔지니어링 마법사는 맞춤 가능한 템플릿들을 제공한다.
+
+
+ Ant 태스크들:
+
+
+
+
+
+ 추가 정보는 Hibernate Tools 패키지와 그것의 문서를 참조하길 바란다.
+
+
+
+ 하지만 Hibernate 메인 패키지는 통합 도구에 번들화 되어 있다(그것은 심지어 플라이 상에서 Hibernate "내에서" 사용될 수 있다):
+ SchemaExport 별칭은 hbm2ddl.
+
+
+
+ 자동적인 스키마 생성
+
+
+ DDL은 Hibernate 유틸리티에 의해 당신의 매핑 파일들로부터 생성될 수 있다. 생성된 스키마는 엔티티 테이블과 콜렉션 테이블에 대한
+ 참조 무결성 컨스트레인트들(프라이머리 키와 foreign 키들)을 포함한다. 테이블들과 시퀀스들은 또한 페칭된 식별자 생성기들에 대해
+ 생성된다.
+
+
+
+ DDL이 매우 벤더에 특정하므로, 이 도구를 사용할 때 당신은 hibernate.dialect 프로퍼티를 통해 한 개의 SQL
+ Dialect를 지정해야 한다.
+
+
+
+ 먼저 생성된 스키마를 개선시키기 위해 당신의 매핑 파일들을 맞춤화 시켜라.
+
+
+
+ 스키마 맞춤화 시키기
+
+
+ 많은 Hibernate 매핑 요소들은 length로 명명된 옵션 속성을 정의한다. 당신은 이 속성으로 컬럼의 길이를
+ 설정할 수 있다.(또는 numeric/decimal 데이터 타입들, 배정도에 대해 ).
+
+
+
+ 몇몇 태그들은 또한 (테이블 컬럼들에 대한 NOT NULL 컨스트레인트를 생성시키는) not-null
+ 속성과 (테이블 컬럼들에 대한 UNIQUE 컨스트레인트를 생성시키는) unique 속성을 수용한다.
+
+
+
+ 몇몇 태그들은 그 컬럼에 대한 인덱스의 이름을 지정하는 index 속성을 허용한다. unique-key
+ 속성은 하나의 단위 키 컨스트레인트로 컬럼들을 그룹지우는데 사용될 수 있다. 현재 unique-key 속성의
+ 지정된 값은 컨스트레인트를 명명하는데 사용되지 않고, 오직 매핑 파일 내에서 컬럼들을 그룹 지우는데
+ 사용된다.
+
+
+
+ 예제들:
+
+
+
+
+
+
+]]>
+
+
+ 다른 방법으로, 이들 요소들은 또한 자식 <column> 요소를 수용한다. 이것은 다중 컬럼 타입들에
+ 특히 유용하다:
+
+
+
+
+]]>
+
+
+
+
+
+]]>
+
+
+ sql-type 속성은 SQL 데이터타입에 대한 Hibernate 타입의 디폴트 매핑을 오버라이드 시키는 것을
+ 사용자에게 허용해준다.
+
+
+
+ check 속성은 check 컨스트레인트를 지정하는 것을 당신에게 허용해준다.
+
+
+
+
+]]>
+
+
+ ...
+
+]]>
+
+
+
+ 요약
+
+
+
+
+
+
+ 속성
+ 값들
+ 해석
+
+
+
+
+ length
+ number
+ 컬럼 길이/decimal 배정도
+
+
+ not-null
+ true|false
+ 컬럼이 null이 아니어야 함을 지정한다
+
+
+ unique
+ true|false
+ 컬럼이 하나의 유일 컨스트레인트를 가져야함을 지정한다
+
+
+ index
+ index_name
+ (다중-컬럼) 인덱스의 이름을 지정한다
+
+
+ unique-key
+ unique_key_name
+ 다중-컬럼 유일 컨스트레인트의 이름을 지정한다
+
+
+ foreign-key
+ foreign_key_name
+
+ 하나의 연관에 대해 생성된 foreign key 컨스트레인트의 이름을 지정하고,
+ <one-to-one>, <many-to-one>, <key>, and <many-to-many>
+ 매핑 요소들 상에 그것을 사용한다. inverse="true" 측들은
+ SchemaExport에 의해 고려되지 않을 것임을 노트하라.
+
+
+
+ sql-type
+ column_type
+
+ 디폴트 컬럼 타입을 오버라이드 시킨다
+ (<column> 요소의 속성에만)
+
+
+
+ check
+ SQL expression
+
+ 컬럼 또는 테이블에 대한 SQL check 컨스트레인트를 생성시킨다
+
+
+
+
+
+
+
+ <comment> 요소는 생성된 스키마에 대한 주석들을 지정하는 것을 당신에게 허용해준다.
+
+
+
+ Current customers only
+ ...
+]]>
+
+
+
+ Balance in USD
+
+]]>
+
+
+ 이것은 (지원되는 경우) 생성된 DDL에서 comment on table 또는
+ comment on column 문장으로 귀결된다.
+
+
+
+
+
+ 도구 실행하기
+
+
+ SchemaExport 도구는 DDL 스크립트를 표준 출력으로 기록 하고/하거나 DDL 문장들을 실행시킨다.
+
+
+
+ java -cp hibernate_classpaths
+ org.hibernate.tool.hbm2ddl.SchemaExportoptions mapping_files
+
+
+
+ SchemaExport 명령 라인 옵션들
+
+
+
+
+
+ 옵션
+ 설명
+
+
+
+
+ --quiet
+ 스크립트를 표준출력으로 출력하지 않는다
+
+
+ --drop
+ 오직 테이블들을 드롭시킨다
+
+
+ --text
+ 데이터베이스로 내보내기 하지 않는다
+
+
+ --output=my_schema.ddl
+ ddl 스크립트를 파일로 출력한다
+
+
+ --config=hibernate.cfg.xml
+ XML 파일로부터 Hibernate 구성을 읽어들인다
+
+
+ --properties=hibernate.properties
+ 파일로부터 데이터베이스 프로퍼티들을 읽어들인다
+
+
+ --format
+ 생성된 SQL을 스크립트 내에 좋게 형식지운다
+
+
+ --delimiter=x
+ 스크립트를 위한 라인 경계의 끝을 설정한다
+
+
+
+
+
+
+ 당신은 당신의 어플리케이션 내에 SchemaExport를 삽입시킬 수도 있다:
+
+
+
+
+
+
+
+ 프로퍼티들
+
+
+ 데이터베이스 프로퍼티들은 다음과 같이 지정될 수 있다
+
+
+
+
+ -D<property>를 가진 시스템 프로퍼티로서
+
+
+ hibernate.properties 내에서
+
+
+ --properties를 가진 명명된 프로퍼티들 내에서
+
+
+
+
+ 필요한 프로퍼티들은 다음과 같다:
+
+
+
+
+
+ 당신은 당신의 어플리케이션 내에 SchemaUpdate를 삽입시킬 수 있다:
+
+
+
+
+
+
+
+ 점증하는 스키마 업데이트들에 Ant 사용하기
+
+
+ 당신은 Ant 스크립트에서SchemaUpdate를 호출할 수 있다:
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+
+
+
+
diff --git a/reference/ko/modules/transactions.xml b/reference/ko/modules/transactions.xml
new file mode 100644
index 0000000000..27be34aaf7
--- /dev/null
+++ b/reference/ko/modules/transactions.xml
@@ -0,0 +1,816 @@
+
+ 트랜잭션들과 동시성
+
+
+ Hibernate와 동시성 제어에 대한 가장 중요한 점은 이해하기가 매우 쉽다는 점이다. Hibernate는 어떤 추가적인 잠금 행위 없이
+ JDBC 커넥션들과 JTA 리소스들을 직접 사용한다. 우리는 당신의 데이터베이스 관리 시스템의 JDBC, ANSI, 그리고 트랜잭션 격리 명세에
+ 약간의 시간을 할애할 것을 매우 권장한다. Hibernate는 단지 자동적인 버전화를 추가하지만 메모리 내에서 객체들을 잠그지 않거나 당신의
+ 데이터베이스 트랜잭션들의 격리 레벨을 변경시키지 않는다. 기본적으로, 당신이 당신의 데이터베이스 리소스들에 직접 JDBC(또는 JTA/CMT)를
+ 사용하는 것처럼 Hibernate를 사용하라.
+
+
+
+ 하지만, 자동적인 버전화에 덧붙여, Hibernate는 또한 SELECT FOR UPDATE 구문을 사용하여,
+ 행들에 대한 pessimistic 잠금을 위한 (마이너) API를 제공한다. 이 API는 이 장의 뒷 부분에서 논의된다.
+
+
+
+ 우리는 Configuration, SessionFactory, Session,
+ 알갱이를 가진 Hibernate에서의 동시성 제어 뿐만 아니라 데이터베이스 트랜잭션과 긴 어플리케이션 트랜잭션에 대한 논의를 시작한다.
+
+
+
+ 세션 영역과 트랜잭션 영역
+
+
+ SessionFactory는 모든 어플리케이션 쓰레드들에 의해 공유되도록 고안된 생성에 비용이 드는,
+ 쓰레드안전(threadsafe) 객체이다. 그것은 대개 어플리케이션 시작 시에 Configuration 인스턴스로부터
+ 한번 생성된다.
+
+
+
+ Session은 단일 비지니스 프로세스, 하나의 작업 단위를 위해 한번만 사용되고 나서 폐기될 예정인,
+ 비용이 들지 않는, 쓰레드 안전하지 않은 객체이다. Session은 그것이 필요하지 않으면 JDBC
+ Connection(또는 Datasource)를 얻지 않을 것이어서, 데이터 접근이
+ 특별한 요청에 서비스할 필요가 있을 것이라고 당신이 확신하지 않을 경우에 당신은 Session을 안전하게
+ 열고 닫을 수 있다. (이것은 당신이 요청 인터셉션을 사용하여 다음 패턴들 중 어떤 것을 구현하자마자 중요하게 된다.)
+
+
+
+ 이 그림을 완성하기 위해 당신은 또한 데이터베이스 트랜재션들에 대해 생각해야 한다. 데이터베이스 트랜잭션은 데이터베이스에서
+ 잠금 다툼을 줄이기 위해 가능한 짧아야 한다. 긴 데이터베이스 트랜잭션들은 당신의 어플리케이션이 고도의 동시성 로드로의 가용성을
+ 높이는 것을 방해할 것이다.
+
+
+
+ 하나의 작업 단위의 영역은 무엇인가? 하나의 Hibernate Session은 몇몇 데이터베이스 트랜잭션들에
+ 걸칠 수 있는가 또는 이것은 영역들의 one-to-one 관계인가? 당신은 언제 Session을 열고 닫는가
+ 그리고 당신은 데이터베이스 트랜잭션 경계들을 어떻게 한정하는가?
+
+
+
+ 작업 단위
+
+
+ 첫번째로, session-per-operation anti-패턴을 사용하지 말라. 즉, 단일 쓰레드 내에서
+ 모든 간단한 데이터베이스 호출에 대해 Session을 열고 닫지 말라! 물론 같은 것이 데이터베이스
+ 트랜잭션들에 대해서도 참이다. 어플리케이션 내의 데이터베이스 호출들은 계획된 순서를사용하여 행해지며, 그것들은 원자
+ 작업 단위 속으로 그룹지워진다. (이것은 또한 모든 하나의 SQL 문장 뒤의 auto-commit(자동-커밋)이 어플리케이션 내에서
+ 무용지물임을 의미하고, 이 모드가 SQL 콘솔 작업을 돕도록 고안되었음을 노트하라. Hibernate는
+ 의미하고, 이 모드는 Hibernate는 즉시 자동-커밋 모드를 사용 불가능하게 하거나, 어플리케이션 서버가 그렇게 행하고,
+ 즉시 자동-커밋시키는 것을 사용불가능하게 하거나 ,그렇게 행하는 것을 기대한다.)
+
+
+
+ 다중 사용자 클라이언트/서버 어플리케이션에서 가장 공통된 패턴은 session-per-request이다.
+ 이 모형에서, 클라이언트로부터의 요청은 (Hibernate 영속 계층이 실행되는) 서버로 전송되고, 새로운 Hibernate
+ Session이 열려지고, 모든 데이터베이스 오퍼레이션들이 이 작업 단위 내에서 실행된다. 일단 그 작업이
+ 완료되었다면(그리고 클라이언트에 대한 응답이 준비되었다면), 그 세션은 flush 되고 닫혀진다. 당신은 또한 당신이
+ Session을 열고 닫을 때 그것을 시작하고 커밋시켜서 클라이언트 요청에 서비스하는데 한 개의 데이터베이스
+ 트랜잭션을 사용하게 될 것이다. 둘 사이의 관계는 일대일 대응이고 이 모형은 많은 어플리케이션들에서 완전하게 적합하다.
+
+
+
+ 도전점은 구현에 놓여있다: Session과 트랜잭션이 정확하게 시작되고 끝나야 할 뿐만 아니라, 그것들은
+ 또한 데이터 접근 오퍼레이션들에 대해 접근 가능해야 한다. 작업의 단위에 대한 경계 구분은 하나의 요청이 서버에 도착하고
+ 응답이 전송되기 전에 실행되는 인터셉터(예를 들면 ServletFilter)를 사용하여 이상적으로 구현된다.
+ 우리는 하나의 ThreadLocal 변수를 사용하여 그 Session을 요청에 서비스하는
+ 쓰레드에 바인드 시킬 것을 권장한다. 이것은 이 쓰레드 내에서 실행되는 모든 코드에서 (static 변수에 접근하는 것처럼) 쉽게
+ 접근을 허용해준다. 당신이 선택하는 데이터베이스 트랜잭션 경계 구분 메커니즘에 따라, 당신은 또한 ThreadLocal
+ 변수 내에 트랜잭션 컨텍스트를 유지할 수도 있다. 이것을 위한 구현 패턴들은ThreadLocal Session
+ 및 뷰 내의 Open Session으로 알려져 있다. 당신은 이것을 구현하기 위해 이 문서의 앞 쪽에 보였던
+ HibernateUtil helper 클래스를 쉽게 확장할 수 있다. 물론 당신은 당신의 환경에서 인터셉터를 구현하고 그것을
+ 설정하는 방법을 찾아야 한다. 팁들과 예제들은 Hibernate 웹 사이트를 보라.
+
+
+
+
+
+ 어플리케이션 트랜잭션들
+
+
+ session-per-request 패턴은 당신이 작업 단위들을 설계하는데 사용할 수 있는 유일한 유용한 개념이 아니다. 많은 비지니스
+ 프로세스들은 데이터베이스 접근들을 중재하는 사용자 사이의 전체 일련의 상호작용들을 필요로 한다. 웹과 엔터프라이즈
+ 어플리케이션에서 사용자 상호작용에 걸치는 것은 데이터베이스 트랜잭션에 허용되지 않는다. 다음 예제를 검토하자:
+
+
+
+
+
+ 대화상자의 첫 번째 화면이 열리고, 사용자에게 보여진 데이터는 특정 Session과 데이터베이스
+ 트랜잭션 속에 로드되었다. 사용자가 객체들을 변경시키는 것이 자유롭다.
+
+
+
+
+
+ 사용자는 5분 후에 "저장"을 클릭하고 그의 변경들이 영속화 되기를 기대한다; 그는 또한 그가 이 정보를 편집하는 유일한
+ 개인이고 변경 충돌이 발생하지 않기를 기대한다.
+
+
+
+
+
+ 우리는 사용자의 관점에서, 이것을 작업 단위, 장기간 실행되는 어플리케이션 트랜잭션이라고 명명한다.
+ 당신이 당신의 어플리케이션에서 이것을 어떻게 구현할 수 있는 많은 방법들이 존재한다.
+
+
+
+ 첫 번째 naive 구현은 동시성 변경을 방지하고, 격리와 atomicity(원자 단위성)을 보장하기 위해 데이터베이스에 의해
+ 소유된 잠금으로 사용자가 생각하는동안 Session과 데이터베이스 트랜잭션을 유지할 수도 있다.
+ 이것은 물론 anti-패턴이다. 왜냐하면 잠금 다툼은 어플리케이션이 동시 사용자들의 가용 숫자를 높이는 것을 허용하지
+ 않을 것이기 때문이다.
+
+
+
+ 명료하게, 우리는 어플리케이션 트랜잭션을 구현하는데 몇몇 데이터베이스 트랜잭션들을 사용해야 한다. 이 경우에,
+ 비지니스 프로세스들의 격리를 유지하는 것은 어플리케이션 티어의 부분적인 책임이 된다. 단일 어플리케이션 트랜잭션은
+ 대개 여러 개의 데이터베이스 트랜잭션들에 걸친다. 그것은 이들 데이터베이스 트랜잭션들 중 오직 한 개(마지막 트랜잭션)가
+ 업데이트된 데이터를 저장하고, 모든 다른 트랜잭션들이 단순히 데이터를 읽는 (예를 들면, 몇몇 요청/응답 주기에 걸치는
+ 마법사 스타일의 대화 상자에서) 경우에만 원자단위가 될 것이다. 특히 당신이 Hibernate의 특징들을 사용할 경우에 , 이것은
+ 들리는 것보다 구현하기가 더 쉽다:
+
+
+
+
+
+ 자동적인 버전화 - Hibernate는 당신을 위해 자동적인 optimistic
+ 동시성 제어를 행할 수 있고, 그것은 사용자가 생각하는 시간 동안 동시적인 변경이 발생했는지를 자동적으로 검출할 수 있다..
+
+
+
+
+ Detached 객체들 - 만일 당신이 이미 논의된 session-per-request
+ 패턴을 사용하고자 결정하는 경우, 모든 로드된 인스턴스들은 사용자가 생각하는 시간 동안 detached 상태에 있을 것이다.
+ Hibernate는 그 객체들을 재첨부시키고 변경들을 영속화 시키는 것을 허용해주며, 그 패턴은
+ session-per-request-with-detached-objects(detached-객체들을 가진 요청 당 세션)으로 명명된다.
+ 자동적인 버전화는 동시성 변경들을 격리시키는데 사용된다.
+
+
+
+
+ Long Session - Hibernate Session은 데이터베이스
+ 트랜잭션이 커밋된 후에 기본 JDBC 커넥션이 연결 해제될 수도 있고, 새로운 클라이언트 요청이 발생할 때 다시 연결될 수
+ 있다. 이 패턴은 session-per-application-transaction(어플리케이션 트랜잭션 당 세션)으로
+ 알려져 있고 재첨부를 불필요하게 만든다. 자동적인 버전화는 동시성 변경들을 격리시키는데 사용된다.
+
+
+
+
+
+ session-per-request-with-detached-objects과
+ session-per-application-transaction 양자는 장점들과 단점들을 갖는데, 우리는 이 장의
+ 뒷 부분에서 optimistic 동시성 제어 단락에서 그것들을 논의한다.
+
+
+
+
+
+ 객체 identity 고려하기
+
+
+ 어플리케이션은 두 개의 다른 Session들 내에 있는 동일한 영속 상태에 동시에 접근할 수도 있다.
+ 하지만 영속 클래스의 인스턴스는 두 개의 Session 인스턴스들 사이에 결코 공유되지 않는다.
+ 그러므로 identity에 대한 두 개의 다른 개념들이 존재한다:
+
+
+
+
+ 데이터베이스 Identity
+
+
+ foo.getId().equals( bar.getId() )
+
+
+
+
+ JVM Identity
+
+
+ foo==bar
+
+
+
+
+
+
+ 그때 (예를 들어 Session 영역에서) 특정Session에
+ 첨부된 객체들의 경우 두 개의 개념들은 동등한 것이고, 데이터베이스 identity에 대한 JVM identity가 Hibernate에 의해 보장된다.
+ 하지만, 어플리케이션이 두 개의 다른 세션들에서 "동일한" (영속 identity) 비지니스 객체에 동시에 접근하는 동안, 두 개의 인스턴스들은
+ 실제로 "다르다"(JVM identity). 충돌들은 flush/커밋 시에 (자동적인 버전화)를 사용하여, optimistic 접근법을 사용하여 해결된다.
+
+
+
+ 이 접근법은 Hibernate와 데이터베이스가 동시성에 대해 걱정하지 않도록 해준다; 그것은 또한 최상의 scalability를 제공한다.
+ 왜냐하면 단일 쓰레드-작업 단위 내에서 identity 보장은 단지 비용이 드는 잠금이나 다른 동기화 수단들을 필요로 하지 않기 때문이다.
+ 어플리케이션은 그것이 Session 당 단일 쓰레드를 강제하는 한, 어떤 비지니스 객체에 대해 결코 동기화 시킬
+ 필요가 없다. 하나의 Session 내에서 어플리케이션은 객체들을 비교하는데 ==를
+ 안전하게 사용할 수가 있다.
+
+
+
+ 하지만, 하나의 Session 외부에서 ==를 사용하는 어플리케이션은 예기치 않은
+ 결과들을 보게 될 수도 있다. 이것은 어떤 예기치 않은 장소들에서, 예를 들어 당신이 두 개의 detached 인스턴스들을 동일한
+ Set 내에 집어넣을 경우에 발생할 수도 있다. 둘 다 동일한 데이터베이스 identity를 가질 수 있지만
+ (예를 들어 그것들은 동일한 행을 표현한다), JVM identity는 정의 상 detached 상태에 있는 인스턴스들을 보장하지 않는다.
+ 개발자는 영속 클래스들내에 equals() 메소드와 hashCode() 메소드를 오버라이드 시켜야 하고
+ 객체 equality에 대한 그 자신의 개념을 구현해야 한다. 하나의 경고가 존재한다: equality를 구현하는데 데이터베이스 identifier를 결코
+ 사용하지 말고, 하나의 비지니스 키, 유일한, 대개 불변인 속성들의 조합을 사용하라. 데이터베이스 식별자는 만일 transient 객체가 영속화되는
+ 경우에 변경될 것이다. 만일 transient 인스턴스가(대개 detached 인스턴스들과 함께) Set 내에 보관되는 경우에,
+ hashcode 변경은 Set의 계약을 파기시킨다. 비지니스 키들에 대한 속성들은 데이터베이스 프라이머리 키들 만큼
+ 안정적이어서는 안되며, 당신은 오직 객체들이 동일한 Set 내에 있는 한에서 안정성을 보장해야만 한다.
+ 이 쟁점에 관한 논의에 대한 더 많은 것을 Hibernate 웹 사이트를 보라. 또한 이것이 Hibernate 쟁점이 아니며, 단지 자바 객체
+ identity와 equality가 구현되어야 하는 방법임을 노트하라.
+
+
+
+
+
+ 공통된 쟁점들
+
+
+ 안티-패턴들 session-per-user-session 또는
+ session-per-application을 결코 사용하지 말라(물론 이 규칙에 대한 드문 예외상황들이 존재한다).
+ 다음 쟁점들 중 몇몇이 또한 권장되는 패턴들로 나타날 수 있음을 노트하고, 당신이 설계 결정을 내리기 전에 내포된 의미들을
+ 확실히 이해하라:
+
+
+
+
+
+ Session은 쓰레드-안전하지 않다. HTTP 요청들, 세션 빈즈, 또는 Swing worker들처럼
+ 동시에 작업하는 것으로 가정되는 것들은 하나의 Session 인스턴스가 공유될 경우에 경쟁 조건들을
+ 발생시킬 것이다. 만일 당신이 당신의 HttpSession 내에 Hibernate
+ Session을 유지시키는 경우(나중에 논의됨), 당신은 당신의 Http 세션에 대한 접근을 동기화
+ 시키는 것을 고려해야 한다. 그 밖의 경우, 충분히 빠르게 reload를 클릭하는 사용자는 두 개의 동시적으로 실행되는
+ 쓰레드들 내에서 동일한 Session을 사용할 수도 있다.
+
+
+
+
+ Hibernate에 의해 던져진 예외상황은 당신이 당신의 데이터베이스 트랜잭션을 롤백 시키고 즉시 Session을
+ 닫아야 함을 의미한다(나중에 상세히 논의됨). 만일 당신의 Session이 어플리케이션에 바인드 되어 있는 경우,
+ 당신은 어플리케이션을 중지시켜야 한다. 데이터베이스 트랜잭션 롤백은 당신의 비지니스 객체들을 그것들이 트랜잭션의 시작 시에
+ 머물렀던 상태로 되돌리지는 않는다. 이것은 데이터베이스 상태와 비지니스 객체들이 동기화를 벗어남을 의미한다. 대개 이것은 문제가 아니다.
+ 왜냐하면 예외상황들은 회복가능한 것이 아니고 당신이 어떻게든 롤백 후에 시작해야 하기 때문이다.
+
+
+
+
+ Session은 (Hibernate에 의해 dirty 상태로 관찰되었거나 체크된) 영속 상태에 있는
+ 모든 객체를 캐시 시킨다. 이것은 당신이 오랜 시간 동안 Session을 열어둔 채로 유지하거나
+ 단순하게 너무 많은 데이터를 로드시킬 경우에, 당신이 OutOfMemoryException을 얻기 전까지, 그것이 끝없이
+ 성장한다는 점을 의미한다. 이것에 대한 하나의 해결책은 Session 캐시를 관리하기 위해
+ clear()와 evict()를 호출하는 것이지만, 당신이 대용량 데이터
+ 오퍼레이션들을 필요로 하는 경우에 당신은 대개 내장 프로시저를 고려해야 할 것이다. 몇몇 해결책들이
+ 에 보여져 있다. 사용자 세션 동안에 Session을 열려진 채로
+ 유지하는 것은 또한 실효성이 떨어진 데이터에 대한 높은 확률을 의미한다.
+
+
+
+
+
+
+
+
+
+ 데이터베이스 트랜잭션 경계 설정
+
+
+ 데이터베이스 (또는 시스템) 트랜잭션 경계들은 항상 필수적이다. 데이터베이스와의 통신은 데이터베이스 트랜잭션의 외부에서 발생할 수
+ 없다(이것은 자동-커밋 모드로 사용되는 많은 개발자들에게는 혼동스러워 보인다). 항상 심지어 읽기 전용 오퍼레이션들에 대해서도 명료한
+ 트랜잭션 경계들을 사용하라. 당신의 격리 레벨과 데이터베이스 가용성들에 따라, 이것은 필요하지 않을 수 있지만, 만일 당신이 항상
+ 트랜잭션들을 명시적으로 경계 설정할 경우에는 하강하는 결점들이 존재하지 않는다.
+
+
+
+ Hibernate 어플리케이션은 관리되지 않는 환경(예를 들면. 스탠드얼론, 간단히 웹 어플리케이션들 또는 Swing 어플리케이션들)과
+ 관리되는 J2EE 환경에서 실행될 수 있다. 관리되지 않는 환경에서, Hibernate는 대개 그것 자신의 데이터베이스 커넥션 풀에 대한
+ 책임이 있다. 어플리케이션 개발자는 트랜잭션 경계들을 손수 설정해야 한다. 달리 말해, 개발자 스스로 데이터베이스 트랜잭션들을
+ 시작하고, 커밋시키거나 롤백시켜야 한다. 관리되는 환경은 대개 예를 들어 EJB 세션 빈즈의 배치 디스크립터 속에 선언적으로 정의된
+ 트랜잭션 어셈블리를 가진, 컨테이너에 의해-관리되는 트랜잭션들을 제공한다. 그때 프로그램 상의 트랜잭션 경계 설정은 더 이상 필요하지
+ 않다. 심지어 Session을 flush 시키는 것이 자동적으로 행해진다.
+
+
+
+ 하지만, 당신의 영속 계층이 이식성을 유지하게끔 자주 희망된다. Hibernate는 당신의 배치 환경의 고유한 트랜잭션 시스템 속으로
+ 변환되는 Transaction이라 명명되는 wrapper API 를 제공한다. 이 API는 실제로 옵션이지만 우리는
+ 당신이 CMT session bean 속에 있지 않는 한 그것의 사용을 강력하게 권장한다.
+
+
+
+ 대개 Session 종료는 네 개의 구분되는 단계들을 수반한다:
+
+
+
+
+
+ 세션을 flush 시킨다
+
+
+
+
+ 트랜잭션을 커밋 시킨다
+
+
+
+
+ 세션을 닫는다
+
+
+
+
+ 예외상황들을 처리한다
+
+
+
+
+
+ 세션을 flush 시키는 것은 앞서 논의되었고, 우리는 이제 관리되는 환경과 관리되지 않는 환경 양자에서 트랜잭션 경계 설정과 예외상황을
+ 더 자세히 살펴볼 것이다.
+
+
+
+
+ 관리되지 않는 환경
+
+
+ 만일 Hibernate 영속 계층이 관리되지 않는(non-managed) 환경에서 실행될 경우, 데이터베이스 커넥션들은 대개 Hibernate의
+ 풀링 메커니즘에 의해 처리된다. session/transaction 처리 관용구는 다음과 같이 보여진다:
+
+
+
+
+
+ 당신은 Session을 명시적으로 flush()시키지 말아야 한다 -
+ commit() 호출은 동기화를 자동적으로 트리거 시킨다.
+
+
+
+ close() 호출은 세션의 종료를 마크한다. close()의 주된 의미는
+ JDBC 커넥션이 그 세션에 의해 포기될 것이라는 점이다.
+
+
+
+ 이 자바 코드는 이식성이 있고 관리되지 않는 환경과 JTA 환경 양자에서 실행된다.
+
+
+
+ 당신은 통상의 어플리케이션에서 비지니스 코드 속에 이 관용구를 결코 보지 않을 것이다; 치명적인(시스템) 예외상황들은 항상
+ "상단"에서 잡혀야 한다. 달리 말해, Hibernate를 실행하는 코드가 (영속 계층에서) 호출되고 RuntimeException을
+ 처리하는 (그리고 대개 오직 제거하고 빠져나갈 수 있는) 코드는 다른 계층들 속에 있다. 이것은 당신 자신이 설계하는 도전점일
+ 수 있고 당신은 J2EE/EJB 컨테이너 서비스들이 이용 가능할 때마다 J2EE/EJB 컨테이너 서비스들을 사용할 것이다. 예외상황
+ 처리는 이 장의 뒷부분에서 논의된다.
+
+
+
+ 당신은 (디폴트인) org.hibernate.transaction.JDBCTransactionFactory를 선택해야 함을 노트하라.
+
+
+
+
+
+ JTA 사용하기
+
+
+ 만일 당신의 영속 계층이 어플리케이션 서버에서(예를 들어, EJB 세션 빈즈 이면에서) 실행될 경우, Hibernate에 의해
+ 획득된 모든 데이터소스 커넥션은 자동적으로 전역 JTA 트랜잭션의 부분일 것이다. Hibernate는 이 통합을 위한 두 개의
+ 방도들을 제공한다.
+
+
+
+ 만일 당신이 bean-managed transactions(BMT)를 사용할 경우 Hibernate는 당신이 Transaction
+ API를 사용할 경우에 BMT 트랜잭션을 시작하고 종료하도록 어플리케이션 서버에게 알려줄 것이다. 따라서 트랜잭션 관리 코드는
+ non-managed 환경과 동일하다.
+
+
+
+
+
+ CMT의 경우, 트랜잭션 관할[경계 설정]은 프로그램 상이 아닌, session bean 배치 디스크립터들 속에서 행해진다. 당신이 스스로
+ Session을 수작업으로 flush 시키고 닫고자 원하지 않을 경우, 단지
+ hibernate.transaction.flush_before_completion을 true로 설정하고,
+ hibernate.connection.release_mode를 after_statement 또는
+ auto로 설정하고 hibernate.transaction.auto_close_session을
+ true로 설정하라. Hibernate는 그때 자동적으로 flush 되고 당신을 위해 Session을
+ 닫을 것이다. 남아 있는 유일한 작업은 예외상황이 발생할 때 트랜잭션을 롤백시키는 것이다. 다행하게도 CMT bean에서, 이것이 자동적으로
+ 일어난다. 왜냐하면 session bean 메소드에 의해 던져진 처리되지 않은 RuntimeException은 전역 트랜잭션을
+ 롤백시키도록 컨테이너에게 통보하기 때문이다. 이것은 당신이 CMT에서 Hibernate Transaction API를
+ 사용할 필요가 전혀 없음을 의미한다.
+
+
+
+ 당신이 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에 의해 완전하게 관리된다.
+
+
+
+ after_statement 커넥션의 사용에는 한 가지 단서가 존재한다. JTA 명세서의 분별없는 제약성으로 인해,
+ scroll() 또는 iterate()에 의해 반환된 어떤 닫혀지지 않은
+ ScrollableResults 또는 Iterator 인스턴스들을 Hibernate가 자동적으로
+ 제거하는 것이 불가능하다. 당신은 finally 블록에서 ScrollableResults.close()
+ 또는 Hibernate.close(Iterator)를 명시적으로 호출하여 기본 데이터베이스 커서를
+ 해제시켜야 한다. (물론 대부분의 어플리케이션들은 CMT 코드에서 scroll()
+ 또는 iterate() 사용을 쉽게 피할 수 있다.)
+
+
+
+
+
+ 예외상황 처리
+
+
+ 만일Session이 (어떤 SQLException을 포함하는) 예외상황을 던질 경우,
+ 당신은 데이터베이스 트랜잭션을 즉시 롤백시키고, Session.close()를 호출하고
+ Session 인스턴스를 폐기시켜야한다. Session의 어떤 메소드들은
+ 그 세션을 일관된 상태로 남겨두지 않을 것이다. Hibernate에 의해 던져진 예외상황은 복구가능한
+ 것으로 취급될 수 없다. 그 Session이 finally 블록 내에서
+ close()를 호출하여 닫혀지도록 확실히 하라.
+
+
+
+ Hibernate 영속 계층에서 발생할 수 있는 대부분의 오류들을 포장하는, HibernateException은
+ 체크되지 않은 예외상황이다(그것은 Hibernate의 이전 버전에는 없었다). 우리의 의견으로, 우리는 낮은 계층에서 복구불가능한
+ 예외상황을 붙잡도록 어플리케이션 개발자에게 강제하지 않을 것이다. 대부분의 시스템들에서, 체크되지 않은 치명적인 예외상황들은
+ (예를 들어, 더 높은 계층에서) 메소드 호출 스택의 첫 번째 프레임들 중 하나 속에서 처리되고, 한 개의 오류 메시지가 어플리케이션
+ 사용자에게 표시된다(또는 어떤 다른 적절한 액션이 취해진다). Hibernate는 또한 HibernateException이
+ 아닌, 다른 체크되지 않은 예외상황들을 던질 수도 있음을 노트하라. 다시 이것들은 복구가능하지 않고 적절한 액션이 취해져야 한다.
+
+
+
+ Hibernate는 데이터베이스와 상호작용하는 동안에 던져진 SQLException들을 하나의
+ JDBCException 속에 포장한다. 사실, Hibernate는 그 예외상황을
+ JDBCException의 보다 의미있는 서브클래스로 변환하려고 시도할 것이다. 기본
+ SQLException은 JDBCException.getCause()를 통해 항상 이용 가능하다.
+ Hibernate는SessionFactory에 첨부된 SQLExceptionConverter를
+ 사용하여 SQLException을 적당한 하나의 JDBCException 서브클래스로
+ 변환시킨다. 디폴트로 SQLExceptionConverter는 구성된 dialect에 의해 정의된다; 하지만
+ 맞춤 구현 속에 플러그인 시키는 것이 또한 가능하다(상세한 것은 SQLExceptionConverterFactory
+ 클래스에 관한 javadocs를 보라). 표준 JDBCException 서브타입은 다음과 같다:
+
+
+
+
+
+ JDBCConnectionException - 기본 JDBC 통신에 대한 오류를 나타낸다.
+
+
+
+
+ SQLGrammarException - 생겨난 SQL에 대한 문법 또는 구문 문제점을 나타낸다.
+
+
+
+
+ ConstraintViolationException - 무결성 제약 위반에 관한 어떤 형식을 나타낸다.
+
+
+
+
+ LockAcquisitionException - 요청된 오퍼레이션을 실행하는데 필수적인 잠금 레벨을
+ 획득하는 오류를 나타낸다.
+
+
+
+
+ GenericJDBCException - 다른 카테고리들 중 어떤 것으로 분류되지 않았던 일반적인 예외상황.
+
+
+
+
+
+
+
+
+
+
+ Optimistic 동시성 제어
+
+
+ 고도의 동시성과 고도의 가용성을 일치시키는 유일한 접근법은 버전화를 가진 optimistic동시성 제어이다. 버전 체킹은 업데이트 충돌을
+ 검출하기 위해(그리고 업데이트 손실을 방지하기 위해) 버전 번호들 또는 timestamp들을 사용한다. Hibernate는 optimistic 동시성을
+ 사용하는 어플리케이션 코드 작성에 세 가지 가능한 접근법들을 제공한다. 우리가 보여주는 쓰임새들은 긴 어플리케이션 트랜잭션들의 상황
+ 속에 있지만 버전 체킹 또한 단일 데이터베이스 트랜잭션들에서 업데이트 손실을 방지하는 이점을 갖고 있다.
+
+
+
+ 어플리케이션 버전 체킹
+
+
+ 하나의 구현에서 Hibernate로부터 많은 도움이 없이, 데이터베이스에 대한 각각의 상호작용은 새로운 Session
+ 내에서 일어나고, 개발자는 영속 인스턴스들을 처리하기 전에 데이터베이스로부터 모든 영속 인스턴스들을 다시 로드시킬 책임이 있다.
+ 이 접근법은 어플리케이션 트랜잭션을 확실히 격리시키기 위해 그것 자신의 버전 체킹을 수행하도록 어플리케이션에게 강제시킨다.
+
+
+
+
+
+ version 프로퍼티는 <version>을 사용하여 매핑되고, Hibernate는 만일 엔티티가 dirty일 경우
+ flush 동안에 그것을 자동적으로 증가시킬 것이다.
+
+
+
+ 물론, 당신이 낮은 데이터 동시성 환경에서 작업하고 있고 버전 체킹을 필요로 하지 않을 경우에, 당신은 이 접근법을 사용할 수 도 있고
+ 단지 버전 체크를 생략할 수도 있다. 그 경우에, 마지막의 커밋 성공은 당신의 긴 어플리케이션 트랜잭션들에
+ 대한 디폴트 방도가 될 것이다. 이것이 어플리케이션의 사용자들을 혼동시킬 수 있음을 염두에 두라. 왜냐하면 사용자들은 오류 메시지들
+ 또는 충돌 변경들을 병합시킬 기회 없이 업데이트들 손실을 겪을 수도 있기 때문이다.
+
+
+
+ 명료하게 수작업 버전 체킹은 매우 사소한 환경들에서도 공포적이고 대부분의 어플리케이션들에 대해 실제적이지 않다. 흔히 단일
+ 인스턴스 뿐만 아니라 변경된 객체들의 전체 그래프들이 체크되어야 한다. Hibernate는 설계 패러다임으로서 긴 Session
+ 또는 detached 인스턴스들에 대해 자동적인 버전 체킹을 제공한다.
+
+
+
+
+
+ 긴 세션과 자동적인 버전화
+
+
+ 하나의 Session 인스턴스와 그것의 영속 인스턴스들은 전체 어플리케이션 트랜잭션에 사용된다. Hibernate는
+ flush 할 때 인스턴스 버전들을 체크하고 만일 동시성 변경이 검출될 경우에 예외상황을 던진다. 이 예외상황을 잡아내고 처리하는 것을
+ 개발자의 몫이다(공통된 옵션들은 변경들을 병합시키거나 또는 쓸모가 없지 않은 데이터로 비지니스 프로세스를 다시 시작하는 기회를
+ 사용자에게 주는 것이다).
+
+
+
+ Session은 사용자 상호작용을 기다릴 때 어떤 기본 JDBC 커넥션으로부터 연결해제된다. 이 접근법은
+ 데이터베이스 접근의 관점에서 보면 가장 효율적이다. 어플리케이션은 버전 체킹 또는 detached 인스턴스들을 재첨부하는 것에
+ 그 자체 관계할 필요가 없거나 그것은 모든 데이터베이스 트랜잭션에서 인스턴스들을 다시 로드시킬 필요가 없다.
+
+
+
+
+
+ foo 객체는 그것이 로드되었던 Session이 어느 것인지를 여전히 알고 있다.
+ Session.reconnect()은 새로운 커넥션을 획득하고(또는 당신이 커넥션을 제공할 수 있다) 그리고
+ 그 세션을 다시 시작시킨다. Session.disconnect() 메소드는 JDBC 커넥션으로부터 세션을
+ 연결 해제하고 (당신이 커넥션을 제공하지 않는 한) 그 커넥션을 풀(pool)로 반환할 것이다. 재연결 후에, 당신이 업데이트하고
+ 있는 데이터에 대한 버전 체킹을 강제시키기 위해, 당신은 또 다른 트랜잭션에 의해 업데이트 되었던 어떤 객체들에 대해
+ LockMode.READ로서 Session.lock()을 호출할 수도 있다. 당신은 당신이
+ 업데이트 중인 어떤 데이터에 대한 잠금을 필요로 하지 않는다.
+
+
+
+
+ 만일 disconnect()와 reconnect()에 대한 명시적인 호출들이 너무 번거러울 경우,
+ 당신은 대신에 hibernate.connection.release_mode를 사용할 수도 있다.
+
+
+
+ 만일 사용자가 생각하는시간 동안 Session이 저장되기에는 너무 큰 경우 이 패턴은 문제성이 있다. 예를 들어
+ HttpSession은 가능한 작은 것으로 유지되어야 한다. 또한 Session은 (필수의)
+ 첫 번째 레벨 캐시이고 모든 로드된 객체들을 포함하기 때문에, 우리는 아마 적은 요청/응답 주기들에 대해서만 이 방도를 사용할 수 있다.
+ Session이 곧 실효성이 없는 데이터를 갖게 될 것이므로 이것이 진정으로 권장된다.
+
+
+
+ 또한 당신이 연결해제된 Session을 영속 계층에 가깝게 유지해야함을 노트하라. 달리말해,
+ Session을 보관하는데 EJB stateful session bean을 사용하고 HttpSession
+ 내에 그것을 저장하기 위해서 그것을 웹 계층에 전송하지 말라(또는 그것을 별도의 티어에 직렬화 시키지도 말라).
+
+
+
+
+
+ Detached 객체들과 자동적인 버전화
+
+
+ 영속 저장소에 대한 각각의 상호작용은 새로운 Session에서 일어난다. 하지만 동일한 영속 인스턴스들은
+ 데이터베이스와의 각각의 상호작용에 재사용된다. 어플리케이션은 원래 로드되었던 detached 인스턴스들의 상태를 또 다른
+ Session 내에서 처리하고 나서 Session.update(),
+ Session.saveOrUpdate(), Session.merge()를 사용하여 그것들을
+ 다시 첨부시킨다.
+
+
+
+
+
+ 다시, Hibernate는 flush 동안에 인스턴스 버전들을 체크할 것이고 업데이트 충돌이 발생할 경우에 예외상황을 던질 것이다.
+
+
+
+ 당신은 또한 update()대신에 lock()을 호출할 수도 있고 만일 그 객체가
+ 변경되지 않았음을 당신이 확신하는 경우에 (버전 체킹을 수행하고 모든 캐시들을 무시하는) LockMode.READ를
+ 사용할 수 있다.
+
+
+
+
+
+ 자동적인 버전화를 맞춤화 시키기
+
+
+ 당신은 optimistic-lock 매핑 속성을 false로 설정함으로써 특정 프로퍼티들과
+ 콜렉션들에 대한 Hibernate의 자동적인 버전 증가를 불가능하도록 할 수도 있다. 그때 Hibernate는 그 프로퍼티가 dirty 일 경우에
+ 더 이상 버전을 증가시키지 않을 것이다.
+
+
+
+ 리거시 데이터베이스 스키마들은 자주 static이고 변경될 수 없다. 또는 다른 어플리케이션들은 또한 동일한 데이터베이스에 접근하고
+ 버전 번호들 또는 심지어 timestamp들을 처리하는 방법을 모를 수도 있다. 두 경우들에서, 버전화는 테이블 내의 특정 컬럼에 의지할 수
+ 없다. version 또는 timestamp 프로퍼티 매핑 없이 행 내의 모든 필드들에 대한 상태를 비교하여 버전 체크를 강제시키기 위해서,
+ <class> 매핑 속에 optimistic-lock="all"을 표시하라. 만일
+ Hibernate가 이전 상태와 새로운 상태를 비교할 수 있을 경우에, 예를 들면 당신이 하나의 긴 Session을
+ 사용하고 session-per-request-with-detached-objects을 사용하지 않을 경우 이것은 개념적으로만 동작함을 노트하라.
+
+
+
+ 때때로 행해졌던 변경들이 중첩되지 않는 한 동시적인 변경이 허용될 수 있다. 만일 <class>를
+ 매핑할 때 당신이 optimistic-lock="dirty"를 설정하면, Hibernate는 flush 동안에 dirty 필드들을
+ 비교만 할 것이다.
+
+
+
+ 두 경우들에서, 전용 version/timestamp 컬럼의 경우 또는 full/dirty 필드 비교의 경우, Hibernate는 법전 체크를 실행하고
+ 정보를 업데이트하는데 엔티티 당 (적절한 WHERE 절을 가진) 한 개의UPDATE
+ 문장을 사용한다. 만일 당신이 연관된 엔티티들에 대한 재첨부를 케스케이드 하는데 transitive 영속을 사용할 경우,
+ Hibernate는 불필요하게 업데이트들을 실행할 수도 있다. 이것은 대개 문제가 아니지만, 심지어 변경들이 detached 인스턴스들에
+ 대해 행해지지 않았을 때에도 데이터베이스 내에서 on update 트리거들이 실행될 수도 있다. 그 행을
+ 업데이트하기 전에 변경들이 실제로 일어났음을 확인하기 위해 인스턴스를 SELECT하는 것을 Hibernate에게
+ 강제시키는, <class> 매핑 속에 select-before-update="true"를
+ 설정함으로써 당신은 이 특징을 맞춤화 시킬 수 있다.
+
+
+
+
+
+
+
+ Pessimistic 잠금
+
+
+ 사용자들은 잠금 방도에 대해 걱정하는데 많은 시간을 할애하하려고 생각하지 않는다. 대개 JDBC 커넥션들에 대한 격리 레벨을 지정하는
+ 것으로 충분하고 그런 다음 단순히 데이터베이스로 하여금 모든 작업을 행하도록 한다. 하지만 진일보한 사용자들은 때때로 배타적인
+ pessimistic 잠금들을 얻거나 또는 새로운 트랜잭션의 시작 시에 잠금들을 다시 얻고자 원할 수도 있다.
+
+
+
+ Hibernate는 결코 메모리 내에 있는 객체들이 아닌, 데이터베이스의 잠금 메커니즘을 항상 사용할 것이다!
+
+
+
+ LockMode 클래스는 Hibernate에 의해 획득될 수 있는 다른 잠금 레벨들을 정의한다. 잠금은 다음 메커니즘들에
+ 의해 얻어진다:
+
+
+
+
+
+ LockMode.WRITE는 Hibernate가 한 행을 업데이트 하거나 insert 할 때 자동적으로 획득된다.
+
+
+
+
+ LockMode.UPGRADE는 SELECT ... FOR UPDATE 구문을 지원하는
+ 데이터베이스 상에서 SELECT ... FOR UPDATE를 사용하여 명시적인 사용자 요청 상에서
+ 얻어질 수 있다.
+
+
+
+
+ LockMode.UPGRADE_NOWAIT는 오라클에서 SELECT ... FOR UPDATE NOWAIT를
+ 사용하여 명시적인 사용자 요청 상에서 얻어질 수도 있다.
+
+
+
+
+ LockMode.READ는 Hibernate가 반복 가능한 읽기(Repeatable Read) 또는 Serialization
+ 격리 레벨에서 데이터를 읽어들일 때 자동적으로 얻어질 수도 있다. 명시적인 사용자 요청에 의해 다시 얻어질 수도 있다.
+
+
+
+
+ LockMode.NONE은 잠금이 없음을 나타낸다. 모든 객체들은 Transaction의 끝에서
+ 이 잠금 모드로 전환된다. update() 또는 saveOrUpdate()에 대한 호출을 통해
+ 세션과 연관된 객체들이 또한 이 잠금 모드로 시작된다.
+
+
+
+
+
+ "명시적인 사용자 요청"은 다음 방법들 중 하나로 표현된다:
+
+
+
+
+
+ LockMode를 지정한 Session.load()에 대한 호출.
+
+
+
+
+ Session.lock()에 대한 호출.
+
+
+
+
+ Query.setLockMode()에 대한 호출.
+
+
+
+
+
+ 만일 Session.load()가 UPGRADE 또는 UPGRADE_NOWAIT
+ 모드로 호출되고 ,요청된 객체가 아직 이 세션에 의해 로드되지 않았다면, 그 객체는 SELECT ... FOR UPDATE를
+ 사용하여 로드된다. 만일 요청된 것이 아닌 다소 제한적인 잠금으로 이미 로드되어 있는 객체에 대해 load()가
+ 호출될 경우, Hibernate는 그 객체에 대해 lock()을 호출한다.
+
+
+
+ 만일 지정된 잠금 모드가 READ, UPGRADE 또는
+ UPGRADE_NOWAIT 일 경우에 Session.lock()은 버전 번호 체크를 수행한다.
+ (UPGRADE 또는 UPGRADE_NOWAIT 인 경우에,
+ SELECT ... FOR UPDATE가 사용된다.)
+
+
+
+ 만일 데이터베이스가 요청된 잠금 모드를 지원하지 않을 경우, (예외상황을 던지는 대신에) Hibernate는 적절한 대체 모드를 사용할 것이다.
+ 이것은 어플리케이션이 이식 가능할 것임을 확실히 해준다.
+
+
+
+
+
+
diff --git a/reference/ko/modules/tutorial.xml b/reference/ko/modules/tutorial.xml
new file mode 100644
index 0000000000..c6406fe61e
--- /dev/null
+++ b/reference/ko/modules/tutorial.xml
@@ -0,0 +1,1139 @@
+
+ Hibernate 개요
+
+
+ 머리말
+
+
+ 이 장은 Hibernate 초심자를 위한 개론적인 튜토리얼이다. 우리는 메모리-내 데이터베이스를
+ 사용하는 간단한 명령 라인 어플리케이션으로 시작하고 단계들을 이해하도록 쉽게 그것을 개발한다.
+
+
+
+
+ 이 튜토리얼은 Hibernate 신규 사용자들을 의도하고 있지만 Java와 SQL 지식을 필요로 한다.
+ 그것은 Michael Gloegl이 작성한 튜토리얼에 기초한다.
+
+
+
+
+
+ 파트 1 - 첫 번째 Hibernate 어플리케이션
+
+
+ 먼저, 우리는 한 개의 간단한 콘솔-기반 Hibernate 어플리케이션을 생성시킬 것이다. 우리는 메모리-내
+ 데이터베이스(HSQL DB)를 사용하므로, 우리는 어떤 데이터베이스 서버를 설치하지 않아도 된다.
+
+
+
+ 우리가 우리가 출석을 원하는 이벤트들을 저장할 수 있는 작은 데이터베이스 어플리케이션과 이들
+ 이벤트들의 호스트들에 대한 정보를 필요로 한다고 가정하자.
+
+
+
+ 우리가 행할 첫 번째 것은 우리의 개발 디렉토리를 설정하고, 우리가 필요로 하는 모든 Java 라이브러리들을
+ 그것 속에 집어 넣는 것이다. Hibernate 웹 사이트로부터 Hibernate 배포본을 내려 받아라. 패키지를
+ 추출해내고 /lib 속에서 발견되는 모든 필요한 라이브러리들을 당신의 새로운 개발 작업
+ 디렉토리의 /lib 디렉토리 속에 위치지워라. 그것은 다음과 같을 것이다:
+
+
+
+
+
+ 이것은 Hibernate에 필요한 최소한의 세트이다(우리는 또한 메인 아카이브인 hibernate3.jar를
+ 복사했음을 노트하라). 필수적인 제 3의 라이브러리와 선택적인 제 3의 라이브러리들에 대한 추가 정보는
+ Hibernate 배포본의 lib/ 디렉토리 속에 있는 README.txt 파일을 보라.
+ (실제로, Log4j는 필수적이지는 않지만 많은 개발자들에 의해 선호된다.)
+
+
+
+ 다음으로 우리는 우리가 데이터베이스 속에 저장시키고자 원하는 이벤트를 표현하는 한 개의 클래스를 생성시킨다.
+
+
+
+ 첫 번째 클래스
+
+
+ 우리의 첫 번째 영속 클래스는 몇몇 프로퍼티들을 가진 간단한 자바빈즈 클래스이다:
+
+
+
+
+
+ 당신은 이 클래스가 프로퍼티 getter와 setter 메소드들에 대한 표준 자바빈즈 명명법들 뿐만 아니라 필드들에 대한
+ private 가시성을 사용하고 있음을 알 수 있다. 이것은 권장되는 설계이지만, 필수적이지는 않다. Hibernate는
+ 또한 필드들에 직접 접근할 수 있으며, accessor 메소드들의 이점은 강건한 리팩토링이다.
+
+
+
+ id 프로퍼티는 특별한 이벤트를 위한 유일 식별자를 소유한다. 만일 우리가 Hibernate의
+ 전체 특징을 사용하고자 원할 경우 모든 영속 엔티티 클래스들(보다 덜 중요한 종속 클래스들 또한 존재한다)은 그런
+ 식별자 프로퍼티를 필요로 할 것이다. 사실 대부분의 어플리케이션들(특히 웹 어플리케이션들)은 식별자에 의해
+ 객체들을 구분지을 필요가 있어서, 당신은 이것을 어떤 제한이라기 보다는 하나의 특징으로 간주할 것이다. 하지만
+ 우리는 대개 객체의 항등(identity)를 처리하지 않으므로, setter 메소드는 private이어야 한다. 객체가 저장될 때,
+ Hibernate는 단지 식별자를 할당할 것이다. 당신은 Hibernate가 public, private, protected 접근자 메소드들
+ 뿐만 아니라 (public, private, protected) 필드들에도 직접 접근할 수 있음을 알 수 있다. 선택은 당신에게 달려
+ 있으며, 당신은 당신의 어플리케이션 설계에 적합하도록 그것을 부합시킬 수 있다.
+
+
+
+ 아규먼트 없는 생성자는 모든 영속 클래스들에 대한 필요조건이다; Hibernate는 당신을 위해 Java Reflection을
+ 사용하여 객체들을 생성시켜야 한다. 하지만 생성자는 private 일 수 있고, 패키지 가시성은 런타임 프락시 생성과
+ 바이트코드 방편 없는 효율적인 데이터 검색에 필요하다.
+
+
+
+ 이 Java 노스 파일을 개발 폴더 내의 src로 명명된 디렉토리 속에 있는 위치지워라. 이제
+ 그 디렉토리는 다음과 같을 것이다:
+
+
+
++src
+ Event.java]]>
+
+
+ 다음 단계에서, 우리는 Hiberante에게 이 영속 클래스에 대해 알려 준다.
+
+
+
+
+
+ 매핑 파일
+
+
+ Hibernate는 영속 크래스들에 대한 객체들을 로드시키고 저장시키는 방법을 알 필요가 있다.
+ 이곳은 Hibernate 매핑 파일이 역할을 행하는 곳이다. 매핑 파일은 Hibernate가 접근해야 하는
+ 데이터베이스 내의 테이블이 무엇인지, 그리고 그것이 사용해야 하는 그 테이블 내의 컬럼들이
+ 무엇인지를 Hibernate에게 알려준다.
+
+
+
+ 매핑 파일의 기본 구조는 다음과 같다:
+
+
+
+
+
+
+[...]
+]]>
+
+
+ Hibernate DTD는 매우 정교하다. 당신은 당신의 편집기 또는 IDE 내에서 XML 매핑 요소들과 속성들에
+ 대한 자동 완성 기능을 위해 그것을 사용할 수 있다. 당신은 또한 당신의 텍스트 편집기 내에 DTD 파일을
+ 열 수 있을 것이다 - 그것은 모든 요소들과 속성들에 대한 전체상을 얻고 디폴트들 뿐만 아니라 몇몇 주석들을
+ 보는 가장 손쉬운 방법이다. Hibernate는 웹으로부터 DTD 파일을 로드시키지 않지만, 먼저 어플리케이션의
+ classpath 경로로부터 그것을 먼저 룩업할 것임을 노트하라. DTD 파일은 hibernate3.jar
+ 속에 포함되어 있을 뿐만 아니라 Hibernate 배포본의 src/ 디렉토리 속에 포함되어
+ 있다.
+
+
+
+ 우리는 코드를 간략화 시키기 위해 장래의 예제에서 DTD 선언을 생략할 것이다. 그것은 물론 옵션이 아니다.
+
+
+
+ 두 개의 hibernate-mapping 태그들 사이에 class 요소를
+ 포함시켜라. 모든 영속 엔티티 클래스들(다시금 종속 클래스들일 수 있고, 그것은 첫번째-급의 엔티티들이 아니다)은
+ SQL 데이터베이스 내의 테이블에 대한 그런 매핑을 필요로 한다:
+
+
+
+
+
+
+
+
+]]>
+
+
+ 지금까지 우리는 그 테이블 내에 있는 한 행에 의해 표현된 각각의 인스턴스인, 클래스의 객체를 영속화 시키고
+ 로드시키는 방법을 Hibernate에게 알려주었다. 이제 우린느 테이블 프라이머리 키에 대한 유일 식별자 프로퍼티 매핑을
+ 계속 행한다. 게다가 우리는 이 식별자를 처리하는 것에 주의를 기울이고자 원하지 않으므로, 우리는 대용 키 프라이머리 키
+ 컬럼에 대한 Hibernate의 식별자 생성 방도를 구성한다:
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ id 요소는 식별자 프로퍼티의 선언이고, name="id"는
+ Java 프로퍼티의 이름을 선언한다 - Hibernate는 그 프로퍼티에 접근하는데 getter 및 setter 메소드들을
+ 사용할 것이다. column 속성은 우리가 EVENTS 테이블의 어느 컬럼을 이 프라이머리 키로
+ 사용하는지를 Hibernate에게 알려준다. 내포된 generator 요소는 식별자 생성 방도를
+ 지정하며, 이 경우에 우리는 increment를 사용했고, 그것은 대개 테스팅(과 튜토리얼들)에
+ 유용한 매우 간단한 메모리-내 숫자 증가 방법이다. Hibernate는 또한 전역적으로 유일한 데이터베이스에 의해 생성된
+ 식별자 뿐만 아니라 어플리케이션에 의해 할당된 식별자(또는 당신이 확장으로 작성한 어떤 방도)를 지원한다.
+
+
+
+ 마지막으로 우리는 매핑 파일 속에서 클래스의 영속 프로퍼티들에 대한 선언들을 포함한다. 디폴트로, 클래스의
+ 프로퍼티들은 영속적인 것으로 간주되지 않는다:
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ id 요소의 경우처럼, property 요소의 name
+ 속성은 사용할 getter 및 setter 메소드들이 어느 것인지를 Hibernate에게 알려준다.
+
+
+
+ date 프로퍼티 매핑은 column 속성을 포함하는데,
+ 왜 title은 column 속성을 포함하지 않는가?
+ column 속성이 없을 경우 Hibernate는 디폴트로 컬럼 이름으로서 프로퍼티 이름을
+ 사용한다. 이것은 에 대해 잘 동작한다. 하지만 date는 대부분의 데이터베이스에서
+ 예약된 키워드이어서, 우리는 그것을 다른 이름으로 더 좋게 매핑 시킨다.
+
+
+
+ 다음 흥미로운 점은 title 매핑 또한 type 속성을 갖지 않는다.
+ 우리가 매핑파일들 속에서 선언하고 사용하는 타입들은 당신이 예상하는 Java 데이터 타입들이 아니다. 그것들은
+ 또한 SQL 데이터베이스 타입들도 아니다. 이들 타입들은 이른바 Hibernate 매핑 타입들,
+ 즉 Java 타입들로부터 SQL 타입들로 변환될 수 있고 반대로 SQL 타입들로부터 Java 타입들로 매핑될 수 있는 컨버터들이다.
+ 다시말해, type 속성이 매핑 속에 존재하지 않을 경우 Hibernate는 정확환 변환 및 매핑 타입
+ 그 자체를 결정하려고 시도할 것이다. 몇몇 경우들에서 (Java 클래스에 대한 Reflection을 사용하는) 이 자동적인 검출은
+ 당신이 예상하거나 필요로 하는 디폴트를 갖지 않을 수도 있다. 이것은 date 프로퍼티를 가진
+ 경우이다. Hibernate는 그 프로퍼티가 SQL date 컬럼, timestamp
+ 컬럼 또는 time 컬럼 중 어느 것으로 매핑되어야 하는지를 알 수가 없다. 우리는 timestamp를
+ 가진 프로퍼티를 매핑함으로써 전체 날짜와 시간 정보를 보존하고 싶다고 선언한다.
+
+
+
+ 다음 매핑 파일은 Event Java 클래스 소스 파일과 같은 디렉토리 속에
+ Event.hbm.xml로서 저장될 것이다. 매핑 파일들에 대한 네이밍은 임의적일 수
+ 있지만, 접미사 hbm.xml은 Hibernate 개발자 공동체 내에서 컨벤션이 되었다.
+ 디렉토리 구조는 이제 다음과 같을 것이다:
+
+
+
++src
+ Event.java
+ Event.hbm.xml]]>
+
+
+ 우리는 Hibernate의 메인 구성을 계속 행한다.
+
+
+
+
+
+ Hibernate 구성
+
+
+ 우리는 이제 적절한 곳에 한 개의 영속 클래스와 그것의 매핑 파일을 갖고 있다. Hibernate를 구성할 차례이다.
+ 우리가 이것을 행하기 전에, 우리는 데이터베이스를 필요로 할 것이다. 자바 기반의 메모리-내 SQL DBMS인
+ HSQL DB는 HSQL DB 웹 사이트에서 내려받을 수 있다. 실제로, 당신은 이 다운로드에서 오직 hsqldb.jar
+ 만을 필요로 한다. 개발 폴더의 lib/ 디렉토리 속에 이 파일을 위치지워라.
+
+
+
+ 개발 디렉토리의 루트에 data로 명명된 디렉토리를 생성시켜라 - 이 디렉토리는
+ HSQL DB가 그것의 데이터 파일들을 저장하게 될 장소이다.
+
+
+
+ Hibernate는 당신의 어플리케이션 내에서 이 데이터베이스에 연결하는 계층이고, 따라서 그것은 커넥션 정보를
+ 필요로 한다. 커넥션들은 마찬가지로 구성되어야 하는 하나의 JDBC 커넥션 풀을 통해 행해진다. Hibernate
+ 배포본은 몇몇 오픈 소스 JDBC 커넥션 풀링 도구들을 포함하고 있지만, 이 튜토리얼에서는 Hibernate에 의해
+ 미리 빌드된 커넥션 풀링을 사용할 것이다. 당신이 필수 라이브러리를 당신의 classpath 속에 복사해야 하고
+ 만일 당신이 제품-특징의 제3의 JDBC 풀링 소프트웨어를 사용하고자 원할 경우에는 다른 커넥션 풀링 설정들을
+ 사용해야 함을 노트하라.
+
+
+
+ Hibernate의 구성을 위해, 우리는 한 개의 간단한 hibernate.properties 파일,
+ 한 개의 약간 더 세련된 hibernate.cfg.xml 파일, 또는 심지어 완전한 프로그램
+ 상의 설정을 사용할 수 있다. 대부분의 사용자들은 XMl 구성 파일을 선호한다:
+
+
+
+
+
+
+
+
+
+
+ org.hsqldb.jdbcDriver
+ jdbc:hsqldb:data/tutorial
+ sa
+
+
+
+ 1
+
+
+ org.hibernate.dialect.HSQLDialect
+
+
+ true
+
+
+ create
+
+
+
+
+
+]]>
+
+
+ 이 XML 구성이 다른 DTD를 사용함을 노트하라. 우리는 Hibernate의 SessionFactory
+ -특정 데이터베이스에 대해 책임이 있는 전역 팩토리-를 구성한다. 만일 당신이 여러 데이터베이스들을
+ 갖고 있다면, (보다 쉬운 시작을 위해) 몇 개의 구성 파일들 속에 여러 개의 <session-factory>
+ 구성들을 사용하라.
+
+
+
+ 처음 네 개의 property 요소들은 JDBC 커넥션을 위한 필수 구성을 포함한다.
+ dialect property 요소는 Hibernate가 발생시키는 특별한 SQL 이형(異形)을
+ 지정한다.
+ hbm2ddl.auto 옵션은 -직접 데이터베이스 속으로- 데이터베이스 스키마의 자동적인
+ 생성을 활성화 시킨다. 물론 이것은 (config 옵션을 제거함으로써) 비활성화 시킬 수 있거나
+ SchemaExport Ant 태스크의 도움으로 파일로 리다이렉트 될 수 있다. 마지막으로
+ 우리는 영속 클래스들을 위한 매핑 파일(들)을 추가시킨다.
+
+
+
+ 이 파일을 소스 디렉토리 속으로 복사하고, 따라서 그것은 classpath의 루트에서 끝날 것이다. Hibernate는
+ 시작 시에 classpath의 루트에서 hibernate.cfg.xml로 명명된 파일을 자동적으로
+ 찾는다.
+
+
+
+
+
+ Ant로 빌드하기
+
+
+ 우리는 이제 Ant로 튜토리얼을 빌드할 것이다. 당신은 Ant를 설치할 필요가 있을 것이다 -
+ Ant 내려받기 페이지에서
+ Ant를 얻어라. Ant를 설치하는 방법은 여기서 다루지 않을 것이다. Ant 매뉴얼을
+ 참조하길 바란다. 당신이 Ant를 설치한 후에, 우리는 빌드파일 생성을 시작할 수 있다. 그것은 build.xml로
+ 명명되고 개발 디렉토리 속에 직접 위치될 것이다.
+
+
+
+ Ant 설치
+
+ 디폴트로 Ant 배포본은 (FAQ에 설명되었듯이) 깨어져 있으며, 예를 들어, 만일 당신이 당신의 빌드 파일 내부에서
+ JUnit를 사용하고자 원할 경우 당신에 의해 정정되어야 한다. JUnit 태스크 작업을 행하기 위해(우리는 이
+ 튜토리얼에서 그것을 필요로 하지 않을 것이다), junit.jar를 ANT_HOME/lib에 복사하거나
+ ANT_HOME/lib/ant-junit.jar 플러그인 스텁을 제거하라.
+
+
+
+
+ 기본 빌드 파일은 다음과 같다:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ 이것은 .jar로 끝나는 lib 디렉토리 내에 있는 모든 파일들을 컴파일에 사용되는 classpath에
+ 추가하도록 Ant에게 알려줄 것이다. 그것은 또한 모든 비-Java 소스 파일들을 대상 디렉토리로 복사할 것이다. 예를 들면,
+ 구성 및 Hibernate 매핑 파일들. 만일 당신이 Ant를 이제 실행할 경우, 당신은 다음 출력을 얻게 될 것이다:
+
+
+ ant
+Buildfile: build.xml
+
+copy-resources:
+ [copy] Copying 2 files to C:\hibernateTutorial\bin
+
+compile:
+ [javac] Compiling 1 source file to C:\hibernateTutorial\bin
+
+BUILD SUCCESSFUL
+Total time: 1 second ]]>
+
+
+
+
+ 시작과 helper들
+
+
+ 몇몇 Event 객체들을 로드시키고 저장할 차례이지만, 먼저 우리는 어떤 인프라스트럭처
+ 코드로 설정을 완료해야 한다. 우리는 Hibernate를 시작해야 한다. 이 시작은 전역 SessionFactory
+ 객체를 빌드하고 어플리케이션 내에서 용이한 접근을 위해 그것을 어떤 곳에 저장하는 것을 포함한다.
+ SessionFactory는 새로운 Session들을 열 수 있다.
+ Session은 작업의 단일-쓰레드 단위를 표현하며, SessionFactory는
+ 한번 초기화 되는 하나의 thread-safe 전역 객체이다.
+
+
+
+ 우리는 시작을 처리하고 Session 처리를 편리하게 해주는 HibernateUtil
+ helper 클래스를 생성시킬 것이다. 이른바 ThreadLocal Session 패턴이 여기서
+ 유용하며, 우리는 현재의 작업 단위를 현재의 쓰레드와 연관지워 유지한다. 구현을 살펴보자:
+
+
+
+
+
+ 이 클래스는 (클래스가 로드될 때 JVM에 의해 한번 호출되는) 그것의 static 초기자 내에 전역 SessionFactory를
+ 산출할 뿐만 아니라 또한 현재 쓰레드에 대한 Session을 소유하는 ThreadLocal 변수를
+ 갖는다. 당신이 HibernateUtil.currentSession()을 호출하는 시점에는 문제가 없으며,
+ 그것은 항상 동일 쓰레드 내에 동일한 Hibernate 작업 단위를 반환할 것이다. HibernateUtil.closeSession()에
+ 대한 호출은 쓰레드와 현재 연관되어 있는 작업 단위를 종료시킨다.
+
+
+
+ 당신이 이 helper를 사용하기 전에 thread-local 변수들에 대한 Java 개념을 확실히 이해하도록 하라.
+ 보다 강력한 HibernateUtil helper는 http://caveatemptor.hibernate.org/에
+ 있는 CaveatEmptor 뿐만 아니라 "Hibernate in Action" 책에서 찾을 수 있다.
+ 당신이 J2EE 어플리케이션 서버 내에 Hibernate를 배치할 경우에 이 클래스는 필수적이지 않다: 하나의
+ Session은 현재의 JTA 트랜잭션에 자동적으로 바인드 될 것이고 당신은 JNDI를 통해
+ SessionFactory를 룩업할 수 있다. 만일 당신이 JBoss AS를 사용할 경우,
+ Hibernate는 관리되는 시스템 서비스로서 배치될 수 있고 SessionFactory를
+ JNDI 이름에 자동적으로 바인드시킬 수 있을 것이다.
+
+
+
+ 개발 소스 디렉토리 속에 HibernateUtil.java 를 위치지우고, 다음으로 Event.java를
+ 위치지워라:
+
+
+
++src
+ Event.java
+ Event.hbm.xml
+ HibernateUtil.java
+ hibernate.cfg.xml
++data
+build.xml]]>
+
+
+ 이것은 문제 없이 다시 컴파일 될 것이다. 우리는 마지막으로 로깅 시스템을 구성할 필요가 있다 - Hibernate는
+ commons logging를 사용하고 Log4j와 JDK 1.4 사이의 선택은 당신의 몫으로 남겨둔다. 대부분의 개발자들은
+ Log4j를 선호한다: Hibernate 배포본에 있는 log4j.properties(이것은 디렉토리
+ etc/ 내에 있다)를 src 디렉토리로 복사하고, 다음으로
+ hibernate.cfg.xml을 복사하라. 예제 구성을 살펴보고 당신이 더 많은 verbose 출력을
+ 원할 경우에 설정들을 변경하라. 디폴트로 Hibernate 시작 메시지는 stdout 상에 보여진다.
+
+
+
+ 튜토리얼 인프라스트럭처는 완전하다 - 그리고 우리는 Hibernate로 어떤 실제 작업을 행할 준비가 되어 있다.
+
+
+
+
+
+ 객체 로딩과 객체 저장
+
+
+ 마지막으로 우리는 객체들을 로드시키고 저장하는데 Hibernate를 사용할 수 있다. 우리는 한 개의 main()
+ 메소드를 가진 한 개의 EventManager 클래스를 작성한다:
+
+
+
+
+
+ 우리는 명령 라인으로부터 몇몇 아규먼트들을 읽어들이고, 만일 첫 번째 아규먼트가 "store"이면, 우리는
+ 새로운 Event를 생성시키고 저장시킨다:
+
+
+
+
+
+ 우리는 한 개의 새로운 Event 객체를 생성시키고, 그것을 Hibernate에게 건네준다.
+ Hibernate는 이제 SQL을 처리하고 데이터베이스 상에서 INSERT들을 실행시킨다.
+ -우리가 이것을 실행하기 전에 코드를 처리하는- Session과 Transaction을
+ 살펴보자.
+
+
+
+ Session은 한 개의 작업 단위이다. 당신은 우리가 추가적인 API, Transactiondmf
+ 갖고 있음에 놀랐을 수도 있다. 이것은 작업 단위가 한 개의 데이터베이스 트랜잭션보다 "더 긴" 경우일 수 있음을 의미한다
+ -웹 어플리케이션 속에서 여러 개의 Http 요청/응답 주기들(예를 들면 마법사 대화상자)에 걸치는 작업 단위를 상상하라.
+ 지금 우리는 그것들을 간단하게 유지할 것이고 Session과 Transaction
+ 사이에 한 개의 one-to-one 입상을 가정할 것이다.
+
+
+
+ Transaction.begin()과 commit()은 무엇을 행하는가?
+ 잘못되는 경우들에서 rollback()은 어디에 있는가? Hibernate
+ Transaction API는 실제 옵션이지만, 우리는 편의와 이식성을 위해 그것을 사용한다.
+ (예를 들어 session.connection.commit()을 호출함으로써)만일 당신 자신이
+ 데이터베이스 트랜잭션을 처리했다면, 당신은 이 직접적인 관리되지 않는 JDBC로 특별한 배치 환경에 그 코드를
+ 바인드시켰다. 당신의 Hibernate 구성 속에서 Transaction을 위한 팩토리를 설정함으로써,
+ 당신은 당신의 영속 계층을 어디에서나 배치할 수 있다. 트랜잭션 처리와 관할에 대한 추가 정보는
+ 를 살펴보라. 우리는 또한 이 예제에서 오류 핸들링과 롤백을 생략했다.
+
+
+
+ 이 첫 번째 루틴을 실행하기 위해서 우리는 호출 가능한 대상을 Ant 빌드 파일에 추가해야 한다:
+
+
+
+
+
+
+
+]]>
+
+
+ action 아규먼트의 값은 대상을 호출할 때 명령 라인 상에서 설정된다:
+
+
+ ant run -Daction=store]]>
+
+
+ 컴파일, 구성에 따른 Hibernate 시작 후에, 당신은 많은 로그 출력을 보게 될 것이다. 끝에서 당신은
+ 다음 라인을 발견할 것이다:
+
+
+
+
+
+ 이것은 Hibernate에 의해 실행된 INSERT이고, 물음표 기호는 JDBC 바인드
+ 파라미터들을 나타낸다. 아규먼트로서 바인드 된 값들을 보거나 장황한 로그를 줄이려면 당신의
+ log4j.properties를 체크하라.
+
+
+
+ 이제 우리는 마찬가지로 저장된 이벤트들을 열거하고자 원하며, 우리는 main 메소드에 한 개의 옵션을
+ 추가한다:
+
+
+
+
+
+ 우리는 또한 새로운 listEvents() method 메소드를 추가 시킨다:
+
+
+
+
+
+ 여기서 우리가 행할 것은 데이터베이스로부터 모든 존재하는 Event 객체들을 로드시키기
+ 위해 HQL (Hibernate Query Language) 질의를 사용하는 것이다. Hibernate는 적절한 SQL을 생성시킬
+ 것이고, 그것을 데이터베이스로 전송하고 데이터를 Event 객체들에 거주시킬 것이다.
+ 당신은 물론 HQL로서 보다 복잡한 질의들을 생성시킬 수 있다.
+
+
+
+ 만일 당신이 이제 -Daction=list 옵션으로 Ant를 호출할 경우, 당신은 당신이 지금까지
+ 저장시켰던 이벤트들을 보게 될 것이다. 당신은 이것이 동작하지 않아서 놀랄 수도 있고, 어쨌든 만일 당신이 이 튜토리얼을
+ 단계적으로 따랐다면 - 그 결과는 항상 공백일 것이다. 이 이유는 Hibernate에서 hbm2ddl.auto
+ 바꿈 때문이다 : Hibernate는 매번 실행 시에 데이터베이스를 다시 생성시킬 것이다. 그 옵션을 제거하여 그것을
+ 사용하지 않도록 하면, 당신이 몇 번의 store 액션을 호출한 후에 당신은 당신의 목록 속에서
+ 결과들을 보게 될 것이다. 자동적인 스키마 생성과 내보내기(export)는 대개 단위 테스팅에서 유용하다.
+
+
+
+
+
+
+
+ 파트 2 - 연관들을 매핑하기
+
+
+ 우리는 한 개의 영속 엔티티 클래스를 한 개의 테이블로 매핑했다. 이것 위에서 빌드하고 몇몇 클래스 연관들을 추가시키자. 먼저
+ 우리는 우리의 어플리케이션에 사람들을 추가하고 그들이 참여하는 이벤트들의 목록을 저장할 것이다.
+
+
+
+ Person 클래스 매핑하기
+
+
+ 클래스의 첫 번째 장면은 간단하다:
+
+
+
+
+
+ Person.hbm.xml로 명명된 새로운 매핑 파일을 생성시켜라:
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ 마지막으로 새로운 매핑을 Hibernate의 구성에 추가하라:
+
+
+
+
+]]>
+
+
+ 이제 우리는 이들 두 개의 엔티티들 사이에 한 개의 연관을 생성시킬 것이다. 명백하게, 개인들은 이벤트들에
+ 참여할 수 있고, 이벤트들은 참여자들을 갖는다. 우리가 다루어야 하는 설계 질문들은 다음과 같다 :
+ 방향성(directionality), 다중성(multiplicity), 그리고 콜렉션 특징.
+
+
+
+
+
+ 단방향 Set-기반의 연관
+
+
+ 우리는 Person 클래스에 이벤트들을 가진 한 개의 콜렉션을 추가할 것이다. 그 방법으로 우리는
+ 명시적인 질의를 실행시키지 않고서 -aPerson.getEvents()를 호출하여- 특정 개인에 대한
+ 이벤트들을 쉽게 네비게이트할 수 있다. 우리는 하나의 Java 콜렉션, Set를 사용한다. 왜냐하면
+ 그 콜렉션은 중복 요소들을 포함하기 않을 것이고 그 순서가 우리와 관련되어 있지 않기 때문이다.
+
+
+
+ 지금까지 우리는 Set으로 구현된 단방향이고 다중 값을 가진 연관들을 설계했다.
+ Java 클래스들 속에 이를 위한 코드를 작성하고 그런 다음 그것을 매핑시키자:
+
+
+
+
+
+ 우리가 이 연관을 매핑하기 전에, 다른 측에 대해 생각하라. 명백하게 우리는 이것을 단지 단방향으로 유지시킬 수 있다.
+ 또는 우리가 그것을 양방향으로 네비게이트하는 것-예를 들어 anEvent.getParticipants()-이
+ 가능하도록 원할 경우에, Event측 상에 또 다른 콜렉션을 생성시킬 수 있다. 이것은 당신에게
+ 남겨진 설계 선택이지만, 이 논의에서 명료한 점은 연관의 다중성이다: 양 측 상에서 "다중" 값을 갖는 경우, 우리는 이것을
+ many-to-many 연관이라고 명명한다. 그러므로 우리는 Hibernate의 many-to-many 매핑을
+ 사용한다:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ Hibernate는 모든 종류의 콜렉션 매핑들, 가장 공통적인 <set>을 지원한다. many-to-many
+ 연관 (또는 n:m 엔티티 관계)의 경우, 한 개의 연관 테이블이 필요하다. 이 테이블 속에 있는 각각의
+ 행은 한 명의 개인과 한 개의 이벤트 사이의 링크를 표현한다. 테이블 이름은 set 요소의 table
+ 속성으로 구성된다. 연관 내의 식별자 컬럼 이름은 개인 측에 대해 <key> 요소로 정의되고
+ 이벤트 측에 대한 컬럼 이름은 <many-to-many>의 column 속성으로
+ 정의된다. 당신은 또한 당신의 콜렉션 내에 있는 객체들의 클래스(정확하게 : 참조들을 가진 콜렉션의 다른 측 상에 있는 클래스)를
+ Hibernate에게 알려주어야 한다
+
+
+
+ 따라서 이 매핑을 위한 데이터베이스 스키마는 다음과 같다:
+
+
+ | *EVENT_ID | | |
+ | EVENT_DATE | | *PERSON_ID | <--> | *PERSON_ID |
+ | TITLE | |__________________| | AGE |
+ |_____________| | FIRSTNAME |
+ | LASTNAME |
+ |_____________|
+ ]]>
+
+
+
+
+ 연관들에 작업하기
+
+
+ EventManager 속에 있는 한 개의 새로운 메소드 내에 몇몇 사람들과 이벤트들을 함께 가져오자:
+
+
+
+
+
+ Person과 Event를 로드시킨 후에, 정규 콜렉션 메소드들을 사용하여
+ 콜렉션을 간단하게 변경하라. 당신이 알 수 있듯이, update() 또는 save()에
+ 대한 명시적인 호출이 존재하지 않고, 변경되었고 저장할 필요가 있는 콜렉션을 Hibernate가 자동적으로 검출해낸다. 이것은
+ 자동적인 dirty 체킹이라 불려지며, 당신은 또한 당신의 임의의 객체들에 대한 name 또는 date
+ 프로퍼티를 변경함으로써 그것을 시도할 수 있다. 그것들이 영속(persistent) 상태에 있는 동안, 즉 특정 Hibernate
+ Session에 바인드되어 있는 동안(예를 들면. 그것들은 작업 단위 속에 방금 로드되었거나 저장되었다),
+ Hibernate는 임의의 변경들을 모니터링하고 쓰기 이면의 형태로 SQL을 실행시킨다. 메모리 상태를 데이터베이스와 동기화 시키는
+ 과정은 대개 오직 작업 단위의 끝에서이고, flushing이라 명명된다.
+
+
+
+ 물론 당신은 다른 작업 단위 속에 개인과 이벤트를 로드시킬 수 도 있다. 또는 당신은 하나의 객체그 영속 상태에 있지 않을 때
+ Session의 외부에서 객체를 변경시킬 수도 있다(만일 객체가 이전에 영속화 되었다면, 우리는 이 상태를
+ detached라고 부른다). (매우 사실적이지 않은) 코드 내에서 이것은 다음과 같을 수 있다:
+
+
+
+
+
+ update에 대한 호출은 한 개의 detached 객체를 영속화 시키고, 당신은 그것이 새로운 작업 단위에
+ 바인드된다고 말할 수 있고, 따라서 detached 동안에 당신이 그것에 대해 행한 임의의 변경들이 데이터베이스에 저장될 수 있다.
+
+
+
+ 물론, 이것은 우리의 현재 상황에서 많이 사용되지 않지만, 그것은 당신이 당신 자신의 어플리케이션 속으로 설계할 수 있는 중요한
+ 개념이다. 지금 한 개의 새로운 액션을 EventManager의 main 메소드에 추가하고 명령 라인에서 그것을
+ 호출하여 이 연습을 완료하라. 만일 당신이 한명의 개인과 한 개의 이벤트에 대한 식별자들을 필요로 할 경우 - save()
+ 메소드가 그것을 반환시킨다.
+
+
+
+ 이것은 두 개의 동등하게 중요한 클래스들, 두 개의 엔티티들 사이에서 한 개의 연관에 관한 예제였다. 앞서 언급했듯이, 전형적인 모형 내에는
+ 다른 클래스들과 타이들이 존재하는데, 대개 "덜 중요하다". 당신은 이미 int 또는 String과
+ 같은 어떤 것을 이미 보았다. 우리는 이들 클래스들을 값 타입들(value types)이라 명명하고, 그들 인스턴스들은
+ 특정 엔티티에 의존한다(depend). 이들 타입들을 가진 인스턴스들은 그것들 자신의 식별성(identity)를 갖지 않거나,
+ 그것들은 엔티티들 사이에서 공유되지도 않는다(두개의 person들은 심지어 그것들이 같은 첫 번째 이름을 갖는 경우에도 동일한 firstname을
+ 참조하지 않는다 ). 물론 값 타입들은 JDK 내에서 발견될 뿐만 아니라(사실, Hibernate 어플리케이션에서 모든 JDK 클래스들은 값 타입들로 간주된다),
+ 당신은 또한 당신 스스로 종속 클래스들, 예를 들면 Address 또는 MonetaryAmount을 작성할 수 있다.
+
+
+
+ 당신은 또한 값 타입들을 설계할 수 있다. 이것은 다른 엔티티들에 대한 참조들을 가진 콜렉션과는 개념적으로 매우 다르지만,
+ Java에서는 대개 동일한 것으로 보여진다.
+
+
+
+
+
+ 값들을 가진 콜렉션
+
+
+ 우리는 값 타입의 객체들을 가진 한 개의 콜렉션을 Person 엔티티에 추가시킨다. 우리는 email 주소를
+ 저장하고자 원하므로, 우리가 사용하는 타입은 String이고, 그 콜렉션은 다시 한 개의 Set이다:
+
+
+
+
+ 이 Set에 대한 매핑은 다음과 같다:
+
+
+
+
+
+]]>
+
+
+ 앞의 매핑과 비교한 차이점은 element 부분인데, 그것은 그 콜렉션이 또 다른 엔티티에 대한
+ 참조들을 포함하지 않을 것이지만 String(소문자 이름은 그것이 Hibernate 매핑 타입/변환자임을
+ 당신에게 말해준다) 타입의 요소들을 가진 한 개의 콜렉션을 포함할 것임을 Hibernate에게 알려준다. 일단 다시 set
+ 요소의 table 속성은 그 콜렉션에 대한 테이블 이름을 결정한다. key 요소는
+ 콜렉션 테이블 내에서 foreign-key 컬럼 이름을 정의한다. element 요소 내에 있는 column
+ 속성은 String 값들이 실제로 저장될 컬럼 이름을 정의한다.
+
+
+
+ 업데이트된 스키마를 살펴보라:
+
+
+ | *EVENT_ID | | | |___________________|
+ | EVENT_DATE | | *PERSON_ID | <--> | *PERSON_ID | <--> | *PERSON_ID |
+ | TITLE | |__________________| | AGE | | *EMAIL_ADDR |
+ |_____________| | FIRSTNAME | |___________________|
+ | LASTNAME |
+ |_____________|
+ ]]>
+
+
+ 당신은 콜렉션 테이블의 프라이머리 키가 사실은 두 컬럼들을 사용하는 한 개의 합성 키(composite key)임을 알 수 있다.
+ 이것은 또한 개인에 대해 email 주소가 중복될 수 없음을 의미하며, 그것은 정확하게 우리가 Java에서 set을 필요로 하는
+ 의미론이다.
+
+
+
+ 마치 개인들과 이벤트들을 링크시켜서 이전에 우리가 행했던 것처럼 이제 당신은 요소들을 시도하고 이 콜렉션에 추가할 수 있다.
+ 그것은 Java에서 동일한 코드이다.
+
+
+
+
+
+ Bi-directional associations
+
+
+ 다음으로 우리는 양방향 연관을 매핑시킬 예정이다-개인과 이벤트 사이에 연관을 만드는 것은 Java에서 양 측들에서 동작한다.
+ 물론 데이터베이스 스키마는 변경되지 않고, 우리는 여전히 many-to-many 다중성을 갖는다. 관계형 데이터베이스는
+ 네트웍 프로그래밍 언어 보다 훨씬 더 유연하여서, 그것은 네비게이션 방향과 같은 어떤 것을 필요로 하지 않는다 - 데이터는
+ 어떤 가능한 바업ㅂ으로 보여질 수 있고 검색될 수 있다.
+
+
+
+ 먼저, 참여자들을 가진 한 개의 콜렉션을 Event Event 클래스에 추가시켜라:
+
+
+
+
+
+ 이제 Event.hbm.xml 내에 연관의 이 쪽도 매핑하라.
+
+
+
+
+
+]]>
+
+
+ 당신이 볼 수 있듯이, 이것들은 두 매핑 문서들 내에서 정규 set 매핑들이다. key와
+ many-to-many에서 컬럼 이름들은 두 매핑 문서들에서 바뀌어진다. 여기서 가장 중요한 부가물은
+ Event의 콜렉션 매핑에 관한 set 요소 내에 있는 inverse="true"
+ 속성이다.
+
+
+
+ 이것이 의미하는 바는 Hibernate가 둘 사이의 링크에 대한 정보를 알 필요가 있을 때 다른 측-Person 클래스-를 취할
+ 것이라는 점이다. 일단 당신이 우리의 두 엔티티들 사이에 양방향 링크가 생성되는 방법을 안다면 이것은 이해하기가 훨씬 더 쉬울 것이다.
+
+
+
+
+
+ 양방향 링크들에 작업하기
+
+
+ 첫 번째로 Hibernate가 정규 Java 의미론에 영향을 주지 않음을 염두에 두라. 우리는 단방향 예제에서 Person과
+ Event 사이에 어떻게 한 개의 링크를 생성시켰는가? 우리는 Event 타입의 인스턴스를
+ Person 타입의 이벤트 참조들을 가진 콜렉션에 추가시켰다. 따라서 명백하게 우리가 이 링크를 양방향으로
+ 동작하도록 만들고자 원한다면, 우리는 다른 측 상에서 -하나의 Person 참조를 하나의 Event
+ 내에 있는 콜렉션에 추가시킴으로써- 동일한 것을 행해야 한다. 이 "양 측 상에 링크 설정하기"는 절대적으로 필수적이고 당신은 그것을 행하는
+ 것을 결코 잊지 말아야 한다.
+
+
+
+ 많은 개발자들은 방비책을 프로그램하고 양 측들을 정확하게 설정하기 위한 하나의 링크 관리 메소드들을 생성시킨다. 예를 들면 Person에서 :
+
+
+
+
+
+ 콜렉션에 대한 get 및 set 메소드드은 이제 protected임을 인지하라 - 이것은 동일한 패키지 내에 있는 클래스들과 서브클래스들이
+ 그 메소드들에 접근하는 것을 허용해주지만, 그 밖의 모든 것들이 그 콜렉션들을 (물론, 대개) 직접 만지는 것을 금지시킨다. 당신은
+ 다른 측 상에 있는 콜렉션에 대해 동일한 것을 행할 것이다.
+
+
+
+ inverse 매핑 속성은 무엇인가? 당신의 경우, 그리고 Java의 경우, 한 개의 양방향 링크는 단순히 양 측들에 대한
+ 참조들을 정확하게 설정하는 문제이다. 하지만 Hibernate는 (컨스트레인트 위배를 피하기 위해서) SQL INSERT 문장과
+ UPDATE 문장을 정확하게 마련하기에 충분한 정보를 갖고 있지 않으며, 양방향 연관들을 올바르게 처리하기 위해
+ 어떤 도움을 필요로 한다. 연관의 한 측을 inverse로 만드는 것은 기본적으로 그것을 무시하고 그것을 다른 측의
+ 거울(mirror)로 간주하도록 Hibernate에게 알려준다. 그것은 Hibernate가 하나의 방향성 네비게이션 모형을
+ 한 개의 SQL 스키마로 변환시킬 때 모든 쟁점들을 잘 해결하는데 필수적인 모든 것이다. 당신이 염두에 두어야 하는 규칙들은 간단하다 :
+ 모든 양방향 연관들은 한 쪽이 inverse일 필요가 있다. one-to-many 연관에서 그것은 many-측이어야 하고,
+ many-to-many 연관에서 당신은 어느 측이든 선택할 수 있으며 차이점은 없다.
+
+
+
+
+
+
+ 요약
+
+
+ 이 튜토리얼은 간단한 스탠드얼론 Hibernate 어플리케이션을 작성하는 기초를 다루었다.
+
+
+
+ 만일 당신이 이미 Hibernate에 자신이 있다고 느낀다면, 당신이 흥미를 찾는 주제들에 대한 참조 문서 목차를 계속 브라우징하라
+ - 가장 많이 요청되는 것은 트랜잭션 처리(), 페치 퍼포먼스(),
+ 또는 API 사용법(), 그리고 질의 특징들()이다.
+
+
+
+ 더 많은(특화된) 튜토리얼들에 대해서는 Hibernate 웹 사이트를 체크하는 것을 잊지 말라.
+
+
+
+
+
\ No newline at end of file
diff --git a/reference/ko/modules/xml.xml b/reference/ko/modules/xml.xml
new file mode 100644
index 0000000000..7bef3aa056
--- /dev/null
+++ b/reference/ko/modules/xml.xml
@@ -0,0 +1,273 @@
+
+ XML 매핑
+
+
+ 이것은 Hibernate3.0에서 실험적인 특징이고 매우 활동적으로 개발 중에 있음을 노트하라.
+
+
+
+ XML 데이터로 작업하기
+
+
+ Hibernate는 당신이 영속 POJO들로 작업하는 것과 아주 동일한 방법으로 영속 XML 데이터에 작업하도록 해준다. 파싱된 XML 트리는
+ 단지 객체 레벨에서 관계형 데이터를 나타내는 또 다른 방법으로 간주될 수 있다. 하나의 파싱된 XML 트리는 POJO들 대신, 객체 레벨에서
+ 관계형 데이터를 표현하는 단지 또 다른 방법으로 간주될 수 있다.
+
+
+
+ Hibernate는 XML 트리들을 처리하는 API로서 dom4j를 지원한다. 당신은 데이터베이스로부터 dom4j 트리들을 검색하고 당신이 그 트리를
+ 데이터베이스와 자동적으로 동기화시키기 위해 어떤 변경을 행하도록 하는 질의들을 작성할 수 있다. 당신은 심지어 XML 문서를 취하고,
+ dom4j를 사용하여 그것을 파싱하고, Hibernate의 다음 기본적인 오퍼레이션들 중 어떤 것으로서 그것을 데이터베이스에 저장시킬 수 있다:
+ persist(), saveOrUpdate(), merge(), delete(), replicate()(merging(병합)은 아직 지원되지
+ 않는다).
+
+
+
+ 이 특징은 데이터 가져오기/내보내기,JMS 또는 SOAP 그리고 XSLT-기반의 레포팅을 통한 엔티티 데이터의 구체화를 포함하는 많은
+ 어플리케이션들을 갖는다.
+
+
+
+ 하나의 매핑은 클래스들의 프로퍼티들과 XML 문서의 노드들을 데이터베이스로 동시에 매핑시키는데 사용될 수 있거나, 만일 매핑할 클래스가
+ 존재하지 않을 경우, 그것은 단지 XML을 매핑시키는데 사용될 수도 있다.
+
+
+
+ XML과 클래스 매핑을 함께 지정하기
+
+
+ 다음은 POJO와 XML을 동시에 매핑시키는 예제이다 :
+
+
+
+
+
+
+
+
+
+
+ ...
+
+]]>
+
+
+
+ XML 매핑만을 지정하기
+
+
+ 다음은 POJO 클래스가 존재하지 않는 예제이다:
+
+
+
+
+
+
+
+
+
+
+ ...
+
+]]>
+
+
+ 이 매핑은 dom4j 트리로서 또는 프로퍼티 name/value 쌍들(java Map들)의 그래프로서 데이터에
+ 접근하는 것을 당신에게 허용해준다. 프로퍼티 이름들은 HQL 질의들 내에서 참조될 수도 있는 순수하게 논리적인 구조체들이다.
+
+
+
+
+
+
+
+ XML 매핑 메타데이터
+
+
+ 많은 Hibernate 매핑 요소들은 node 속성을 수용한다. 이것은 당신이 프로퍼티 또는 엔티티 데이터를 소유하는
+ XML 속성이나 요소의 이름을 지정하도록 한다. node 속성의 포맷은 다음 중 하나이어야 한다:
+
+
+
+
+ "element-name" - 명명된 XML 요소로 매핑시킨다
+
+
+ "@attribute-name" - 명명된 XML 속성으로 매핑시킨다
+
+
+ "." - 부모 요소로 매핑 시킨다
+
+
+
+ "element-name/@attribute-name" -
+ 명명된 요소의 명명된 속성으로 매핑시킨다
+
+
+
+
+
+ 콜렉션들과 단일 값 콜렉션들의 경우, 추가적인 embed-xml 속성이 존재한다. 만일 embed-xml="true"
+ 일 경우, 연관된 엔티티(또는 value 타입을 가진 콜렉션)에 대한 디폴트 XML 트리는 그 연관을 소유하는 엔티티에 대한 XML 트리 속에
+ 직접 삽입될 것이다. 그 밖의 경우 embed-xml="false" 일 경우, 참조된 식별자 값 만이 단일 포인트 연관들에
+ 대해 나타날 것이고 콜렉션들은 단순히 전혀 나타나지 않을 것이다.
+
+
+
+ 당신은 너무 많은 연관들에 대해 embed-xml="true"로 남겨두지 말도록 주의해야 한다. 왜냐하면 XML이
+ 순환적으로 잘 처리하지 못하기 때문이다!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ...
+
+]]>
+
+
+ 이 경우에, 우리는 실제 account 데이터가 아닌, account id들을 가진 콜렉션을 삽입시키기로 결정했다. 다음 HQL 질의:
+
+
+
+
+
+ 는 다음과 같은 데이터셋들을 반환할 것이다:
+
+
+
+ 987632567
+ 985612323
+
+ Gavin
+ A
+ King
+
+ ...
+]]>
+
+
+ 만일 당신이 <one-to-many> 매핑에 대해 embed-xml="true"를 설정할 경우,
+ 데이터는 다음과 같이 보일 수도 있다:
+
+
+
+
+
+ 100.29
+
+
+
+ -2370.34
+
+
+ Gavin
+ A
+ King
+
+ ...
+]]>
+
+
+
+
+
+ XML 데이터 처리하기
+
+
+ 우리의 어플리케이션 내에서 XML 문서들을 다시 읽어들이고 업데이트 시키자. 우리는 dom4j 세션을 얻어서 이것을 행한다:
+
+
+
+
+
+
+
+ XML 기반의 데이터 가져오기/내보내기를 구현하는데 이 특징과 Hibernate의 replicate() 오퍼레이션을
+ 결합시키는 것이 매우 유용하다.
+
+
+
+
+
+
diff --git a/reference/ko/styles/fopdf.xsl b/reference/ko/styles/fopdf.xsl
new file mode 100644
index 0000000000..ca31e23d5d
--- /dev/null
+++ b/reference/ko/styles/fopdf.xsl
@@ -0,0 +1,526 @@
+
+
+
+
+
+]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 버전:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -5em
+ -5em
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 하이버네이트
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ bold
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 0
+
+ 1
+
+
+
+
+
+ book toc
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+ 5mm
+ 10mm
+ 10mm
+
+ 15mm
+ 10mm
+ 0mm
+
+ 18mm
+ 18mm
+
+
+ 0pc
+
+
+
+
+ 11
+
+
+ 1.4
+
+
+
+
+
+
+ 0.8em
+
+
+
+
+
+ 17.4cm
+
+
+
+ 4pt
+ 4pt
+ 4pt
+ 4pt
+
+
+
+ 0.1pt
+ 0.1pt
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ left
+ bold
+
+
+ pt
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0.8em
+ 0.8em
+ 0.8em
+
+
+ pt
+
+ 0.1em
+ 0.1em
+ 0.1em
+
+
+ 0.6em
+ 0.6em
+ 0.6em
+
+
+ pt
+
+ 0.1em
+ 0.1em
+ 0.1em
+
+
+ 0.4em
+ 0.4em
+ 0.4em
+
+
+ pt
+
+ 0.1em
+ 0.1em
+ 0.1em
+
+
+
+
+ bold
+
+
+ pt
+
+ false
+ 0.4em
+ 0.6em
+ 0.8em
+
+
+
+
+
+
+ 1em
+ 1em
+ 1em
+ 0.1em
+ 0.1em
+ 0.1em
+ #444444
+ solid
+ 0.1pt
+ 0.5em
+ 0.5em
+ 0.5em
+ 0.5em
+ 0.5em
+ 0.5em
+
+
+
+ 1
+
+ #F0F0F0
+
+
+
+
+
+ 1
+
+
+ 90
+
+
+ 0
+
+
+
+
+
+
+
+
+ (
+
+ )
+
+
+
+
+
+
+
+
+ figure after
+ example before
+ equation before
+ table before
+ procedure before
+
+
+
+ 1
+
+
+
+ 0.8em
+ 0.8em
+ 0.8em
+ 0.1em
+ 0.1em
+ 0.1em
+
+
+
+
+
+
+ false
+ Gulim
+
+ 가을체
+
+
+
+
+
diff --git a/reference/ko/styles/html.css b/reference/ko/styles/html.css
new file mode 100644
index 0000000000..d6342f562a
--- /dev/null
+++ b/reference/ko/styles/html.css
@@ -0,0 +1,97 @@
+A {
+ color: #003399;
+}
+
+A:active {
+ color: #003399;
+}
+
+A:visited {
+ color: #888888;
+}
+
+P, OL, UL, LI, DL, DT, DD, BLOCKQUOTE {
+ color: #000000;
+}
+
+TD, TH, SPAN {
+ color: #000000;
+}
+
+BLOCKQUOTE {
+ margin-right: 0px;
+}
+
+
+H1, H2, H3, H4, H5, H6 {
+ color: #000000;
+ font-weight:500;
+ margin-top:10px;
+ padding-top:15px;
+}
+
+TABLE {
+ border-collapse: collapse;
+ border-spacing:0;
+ border: 1px thin black;
+ empty-cells: hide;
+}
+
+TD {
+ padding: 4pt;
+}
+
+H1 { font-size: 150%; }
+H2 { font-size: 140%; }
+H3 { font-size: 110%; font-weight: bold; }
+H4 { font-size: 110%; font-weight: bold;}
+H5 { font-size: 100%; font-style: italic; }
+H6 { font-size: 100%; font-style: italic; }
+
+TT {
+font-size: 90%;
+ font-family: "Courier New", Courier, monospace;
+ color: #000000;
+}
+
+PRE {
+font-size: 100%;
+ padding: 5px;
+ border-style: solid;
+ border-width: 1px;
+ border-color: #CCCCCC;
+ background-color: #F4F4F4;
+}
+
+UL, OL, LI {
+ list-style: disc;
+}
+
+HR {
+ width: 100%;
+ height: 1px;
+ background-color: #CCCCCC;
+ border-width: 0px;
+ padding: 0px;
+ color: #CCCCCC;
+}
+
+.variablelist {
+ padding-top: 10;
+ padding-bottom:10;
+ margin:0;
+}
+
+.itemizedlist, UL {
+ padding-top: 0;
+ padding-bottom:0;
+ margin:0;
+}
+
+.term {
+ font-weight:bold;
+}
+
+
+
+
diff --git a/reference/ko/styles/html.xsl b/reference/ko/styles/html.xsl
new file mode 100644
index 0000000000..b670405b43
--- /dev/null
+++ b/reference/ko/styles/html.xsl
@@ -0,0 +1,84 @@
+
+
+
+
+
+]>
+
+
+
+
+
+
+
+ ../shared/css/html.css
+
+
+ 1
+ 0
+ 1
+ 0
+
+
+
+
+
+ book toc
+
+
+
+ 3
+
+
+
+
+ 1
+
+
+
+
+
+
+ 0
+
+
+ 90
+
+
+
+
+
+ figure after
+ example before
+ equation before
+ table before
+ procedure before
+
+
+
diff --git a/reference/ko/styles/html_chunk.xsl b/reference/ko/styles/html_chunk.xsl
new file mode 100644
index 0000000000..1e1afc785f
--- /dev/null
+++ b/reference/ko/styles/html_chunk.xsl
@@ -0,0 +1,86 @@
+
+
+
+
+
+]>
+
+
+
+
+
+
+
+ '5'
+ '1'
+ ../shared/css/html.css
+
+
+ 1
+ 0
+ 1
+ 0
+
+
+
+
+
+ book toc
+
+
+
+ 3
+
+
+
+
+ 1
+
+
+
+
+
+
+ 0
+
+
+ 90
+
+
+
+
+
+ figure after
+ example before
+ equation before
+ table before
+ procedure before
+
+
+