hibernate-orm/reference/ko/modules/basic_mapping.xml
JongDae Kim a6607faacc v31final
git-svn-id: https://svn.jboss.org/repos/hibernate/trunk/Hibernate3/doc@9072 1b8cb986-b30d-0410-93ca-fae66ebed9b2
2006-01-17 04:13:35 +00:00

3141 lines
180 KiB
XML

<chapter id="mapping">
<title>기본 O/R 매핑</title>
<sect1 id="mapping-declaration" revision="1">
<title>매핑 선언</title>
<para>
객체/관계형 매핑들은 대개 XML 문서 내에 정의된다. 매핑 문서는 가독성이 있고 수작업 편집이 가능하도록
설계되어 있다. 매핑 언어는 매핑들이 테이블 선언들이 아닌, 영속 클래스 선언들로 생성된다는 의미에서
자바 중심적이다.
</para>
<para>
심지어 많은 Hibernate 사용자들이 수작업으로 XML을 작성하고자 선택할지라도, XDoclet, Middlegen,
그리고 AndroMDA를 포함하는, 매핑 문서를 생성시키는 많은 도구들이 존재한다는 점을 노트하라.
</para>
<para>
예제 매핑으로 시작하자:
</para>
<programlisting id="mapping-declaration-ex1" revision="1"><![CDATA[<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="eg">
<class name="Cat"
table="cats"
discriminator-value="C">
<id name="id">
<generator class="native"/>
</id>
<discriminator column="subclass"
type="character"/>
<property name="weight"/>
<property name="birthdate"
type="date"
not-null="true"
update="false"/>
<property name="color"
type="eg.types.ColorUserType"
not-null="true"
update="false"/>
<property name="sex"
not-null="true"
update="false"/>
<property name="litterId"
column="litterId"
update="false"/>
<many-to-one name="mother"
column="mother_id"
update="false"/>
<set name="kittens"
inverse="true"
order-by="litter_id">
<key column="mother_id"/>
<one-to-many class="Cat"/>
</set>
<subclass name="DomesticCat"
discriminator-value="D">
<property name="name"
type="string"/>
</subclass>
</class>
<class name="Dog">
<!-- mapping for Dog could go here -->
</class>
</hibernate-mapping>]]></programlisting>
<para>
우리는 이제 매핑 문서의 내용을 논의할 것이다. 우리는 Hibernate에 의해 실행 시에 사용되는 문서 요소들과
속성들 만을 설명할 것이다. 매핑 문서는 또한 스키마 내보내기 도구에 의해 내보내진 데이터베이스 스키마에
영향을 주는 어떤 특별한 옵션 속성들과 요소들을 포함한다. (예를 들어 <literal>not-null</literal> 속성.)
</para>
<sect2 id="mapping-declaration-doctype" revision="2">
<title>Doctype</title>
<para>
모든 XML 매핑들은 doctype이 보이게 선언해야 한다. 실제 DTD는 위의 URL에서,
<literal>hibernate-x.x.x/src/org/hibernate</literal> 디렉토리 내에서 또는 <literal>hibernate3.jar</literal>
내에서 찾을 수 있다. Hibernate는 항상 첫 번째로 그것의 classpath 속에서 DTD를 찾게 될 것이다. 만일
당신이 인터넷 연결을 사용하는 DTD에 대한 룩업들을 겪게 될 경우, 당신의 classpath의 컨텐츠에 대해 당신의 DTD 선언을
체크하라.
</para>
</sect2>
<sect2 id="mapping-declaration-mapping" revision="3">
<title>hibernate-mapping</title>
<para>
이 요소는 몇 개의 선택적인 속성들을 갖는다. <literal>schema</literal> 속성과 <literal>catalog</literal>
속성은 이 매핑 내에서 참조된 테이블들이 명명된 schema 와/또는 catalog에 속한다는 점을 지정한다. 만일 지정될 경우,
테이블 이름들은 주어진 schema 이름과 catalog 이름에 의해 한정(수식)될 것이다. 누락될 경우, 테이블 이름들은
한정되지((수식어가 붙지) 않을 것이다. <literal>default-cascade</literal> 속성은 <literal>cascade</literal>
속성을 지정하지 않은 프로퍼티들과 콜렉션들에 대해 전제될 <literal>cascade</literal> 스타일이 무엇인지를 지정한다.
<literal>auto-import</literal> 속성은 디폴트로 우리가 질의 언어 속에서 수식어가 붙지 않은(unqualified)
클래스 이름들을 사용하게 할 것이다.
</para>
<programlistingco>
<areaspec>
<area id="hm1" coords="2 55"/>
<area id="hm2" coords="3 55"/>
<area id="hm3" coords="4 55"/>
<area id="hm4" coords="5 55"/>
<area id="hm5" coords="6 55"/>
<area id="hm6" coords="7 55"/>
<area id="hm7" coords="8 55"/>
</areaspec>
<programlisting><![CDATA[<hibernate-mapping
schema="schemaName"
catalog="catalogName"
default-cascade="cascade_style"
default-access="field|property|ClassName"
default-lazy="true|false"
auto-import="true|false"
package="package.name"
/>]]></programlisting>
<calloutlist>
<callout arearefs="hm1">
<para>
<literal>schema</literal> (옵션): 데이터베이스 스키마의 이름.
</para>
</callout>
<callout arearefs="hm2">
<para>
<literal>catalog</literal> (옵션): 데이터베이스 카다록의 이름.
</para>
</callout>
<callout arearefs="hm3">
<para>
<literal>default-cascade</literal> (옵션 - 디폴트는 <literal>none</literal>):
디폴트 cascade 스타일.
</para>
</callout>
<callout arearefs="hm4">
<para>
<literal>default-access</literal> (옵션 - 디폴트는 <literal>property</literal>):
Hibernate가 모든 프로퍼티들에 액세스하는데 사용하게 될 방도. <literal>PropertyAccessor</literal>
대한 맞춤형 구현일 수 있다.
</para>
</callout>
<callout arearefs="hm5">
<para>
<literal>default-lazy</literal> (옵션 - 디폴트는 <literal>true</literal>):
class 및 collection 매핑들의 지정되지 않은 <literal>lazy</literal> 속성들에 대한 디폴트 값.
</para>
</callout>
<callout arearefs="hm6">
<para>
<literal>auto-import</literal> (옵션 - 디폴트는 <literal>true</literal>):
우리가 질의 언어 내에 (이 매핑에서 클래스들에 대해) 수식어가 붙지 않은 클래스 이름들을 사용할 수 있는지를
지정한다.
</para>
</callout>
<callout arearefs="hm7">
<para>
<literal>package</literal> (옵션): 매핑 문서 내에서 수식어가 붙지 않은 클래스 이름들에 대해
가정할 패키지 접두어를 지정한다.
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
만일 당신이 동일한 (수식어가 붙지 않은) 이름을 가진 두 개의 영속 클래스들을 갖고 있다면, 당신은 <literal>auto-import="false"</literal>
설정해야 한다. 만일 당신이 두 개의 클래스들에 동일한 "imported" 이름을 할당하려고 시도할 경우에 Hibernate는 예외상황을 던질 것이다.
</para>
<para>
위에 보여진 것처럼 <literal>hibernate-mapping</literal> 요소는 몇몇 영속 <literal>&lt;class&gt;</literal> 매핑들을 내부에 포함하는
것을 허용해준다는 점을 노트하라. 하지만 한 개의 매핑 파일 속에 한 개의 영속 클래스(또는 한 개의 클래스 계층구조) 만을 매핑하고 영속 서브 클래스 뒤에
그것을 명명하는 것이 좋은 연습이다 (그리고 몇몇 도구들에 의해 기대된다). 예를 들면 <literal>Cat.hbm.xml</literal>,
<literal>Dog.hbm.xml</literal> 또는 상속을 사용할 경우에는 <literal>Animal.hbm.xml</literal>.
</para>
</sect2>
<sect2 id="mapping-declaration-class" revision="3">
<title>class</title>
<para>
당신은 <literal>class</literal> 요소를 사용하여 영속 클래스를 선언할 수도 있다:
</para>
<programlistingco>
<areaspec>
<area id="class1" coords="2 55"/>
<area id="class2" coords="3 55" />
<area id="class3" coords="4 55"/>
<area id="class4" coords="5 55" />
<area id="class5" coords="6 55"/>
<area id="class6" coords="7 55" />
<area id="class7" coords="8 55"/>
<area id="class8" coords="9 55" />
<area id="class9" coords="10 55" />
<area id="class10" coords="11 55"/>
<area id="class11" coords="12 55"/>
<area id="class12" coords="13 55"/>
<area id="class13" coords="14 55"/>
<area id="class14" coords="15 55"/>
<area id="class15" coords="16 55"/>
<area id="class16" coords="17 55"/>
<area id="class17" coords="18 55"/>
<area id="class18" coords="19 55"/>
<area id="class19" coords="20 55"/>
<area id="class20" coords="21 55"/>
<area id="class21" coords="22 55"/>
</areaspec>
<programlisting><![CDATA[<class
name="ClassName"
table="tableName"
discriminator-value="discriminator_value"
mutable="true|false"
schema="owner"
catalog="catalog"
proxy="ProxyInterface"
dynamic-update="true|false"
dynamic-insert="true|false"
select-before-update="true|false"
polymorphism="implicit|explicit"
where="arbitrary sql where condition"
persister="PersisterClass"
batch-size="N"
optimistic-lock="none|version|dirty|all"
lazy="true|false"
entity-name="EntityName"
check="arbitrary sql check condition"
rowid="rowid"
subselect="SQL expression"
abstract="true|false"
node="element-name"
/>]]></programlisting>
<calloutlist>
<callout arearefs="class1">
<para>
<literal>name</literal> (옵션): 영속 클래스(또는 인터페이스)의 전체 수식어가 붙은 Java 클래스 이름.
만일 이 속성이 누락될 경우, 매핑이 non-POJO 엔티티라고 가정된다.
</para>
</callout>
<callout arearefs="class2">
<para>
<literal>table</literal> (옵션 - 디폴트는 수식어가 붙지 않은 클래스명): 그것의 데이터베이스 테이블의 이름.
</para>
</callout>
<callout arearefs="class3">
<para>
<literal>discriminator-value</literal> (옵션 - 디폴트는 클래스 이름): 다형성(polymorphic) 특징에 사용되는,
개별 서브 클래스들를 구별짓는 값. 허용가능한 값들은<literal>null</literal><literal>not null</literal>을 포함한다.
</para>
</callout>
<callout arearefs="class4">
<para>
<literal>mutable</literal> (옵션 - 디폴트는 <literal>true</literal>): 클래스들의 인스턴스들이 가변적인지를
(가변적이지 않은지를) 지정한다.
</para>
</callout>
<callout arearefs="class5">
<para>
<literal>schema</literal> (옵션): 루트 <literal>&lt;hibernate-mapping&gt;</literal> 요소에 의해 지정된
스키마 이름을 오버라이드 시킨다.
</para>
</callout>
<callout arearefs="class6">
<para>
<literal>catalog</literal> (옵션): 루트 <literal>&lt;hibernate-mapping&gt;</literal> 요소에 의해 지정된
카다록 이름을 오버라이드 시킨다.
</para>
</callout>
<callout arearefs="class7">
<para>
<literal>proxy</literal> (옵션): lazy initializing proxy들에 사용할 인터페이스를 지정한다. 당신은 클래스
그 자체의 이름을 지정할 수 도 있다.
</para>
</callout>
<callout arearefs="class8">
<para>
<literal>dynamic-update</literal> (옵션 - 디폴트는 <literal>false</literal>):
<literal>UPDATE</literal> SQL이 실행 시에 생성되고 그들 컬럼들의 값들이 변경된 그들 컬럼들 만을
포함할 것인지를 지정한다.
</para>
</callout>
<callout arearefs="class9">
<para>
<literal>dynamic-insert</literal> (옵션 - 디폴트는 <literal>false</literal>):
생성될 <literal>INSERT</literal>이 실행 시에 생성되고 그들 컬럼들의 값이 null이 아닌 컬럼들 만을
포함할 것인지를 지정한다.
</para>
</callout>
<callout arearefs="class10">
<para>
<literal>select-before-update</literal> (옵션 - 디폴트는 <literal>false</literal>):
객체가 실제로 변경되는 것이 확실하지 않는 한, Hibernate가 SQL <literal>UPDATE</literal>
<emphasis>결코</emphasis> 실행하지 않을 것임을 지정한다. 어떤 경우들에서(실제로 transient
객체가 <literal>update()</literal>를 사용하여 새로운 session에 연관되었을 때에만), 이것은
하나의 <literal>UPDATE</literal>가 실제로 필요한 경우인지 여부를 결정하기 위해 Hibernate는
특별한 SQL <literal>SELECT</literal>를 실행할 것임을 의미한다.
</para>
</callout>
<callout arearefs="class11">
<para>
<literal>polymorphism</literal> (옵션 - 디폴트는 <literal>implicit</literal>):
implicit 질의 다형성이나 explicit 질의 다형성 중 어느 것이 사용될 것인지를 결정한다.
</para>
</callout>
<callout arearefs="class12">
<para>
<literal>where</literal> (옵션) 이 클래스의 객체들을 검색할 때 사용될 임의적인 SQL
<literal>WHERE</literal> 조건을 지정한다
</para>
</callout>
<callout arearefs="class13">
<para>
<literal>persister</literal> (옵션): 맞춤형 <literal>ClassPersister</literal>를 지정한다.
</para>
</callout>
<callout arearefs="class14">
<para>
<literal>batch-size</literal> (옵션 - 디폴트는 <literal>1</literal>) 식별자에 의해 이 클래스의
인스턴스들을 페치시키는 "배치 사이즈"를 지정한다.
</para>
</callout>
<callout arearefs="class15">
<para>
<literal>optimistic-lock</literal> (옵션 - 디폴트는 <literal>version</literal>):
optimistic 잠금 방도를 결정한다.
</para>
</callout>
<callout arearefs="class16">
<para>
<literal>lazy</literal> (옵션): <literal>lazy="false"</literal>를 설정함으로써
Lazy fetching이 전체적으로 사용불가능하게 될 수 있다.
</para>
</callout>
<callout arearefs="class17">
<para>
<literal>entity-name</literal>(옵션, 디폴트는 클래스 이름): Hibernate3는 하나의 클래스가
(잠정적으로 다른 테이블들로) 여러번 매핑되는 것을 허용해주고, Java 레벨에서 Map 또는 XML에 의해 표현
되는 엔티티 매핑들을 허용한다. 이들 경우들에서, 당신은 그 엔티티에 대한 명시적인 임의의 이름을 제공해야 한다.
<literal>entity-name</literal> (옵션): Hibernate3는 하나의 클래스가 (잠정적으로 다른 테이블들로)
여러 번 매핑되는 것을 허용하며, 자바 레벨에서 Map들 또는 XML에 의해 표현되는 엔티티 매핑들을 허용한다.
이들 경우들에서, 당신은 그 엔티티들에 대한 명시적인 임의의 이름을 제공해야 한다. 추가 정보는
<xref linkend="persistent-classes-dynamicmodels"/><xref linkend="xml"/>을 보라.
</para>
</callout>
<callout arearefs="class18">
<para>
<literal>check</literal> (옵션): 자동적인 스키마 생성을 위한 다중-행 <emphasis>check</emphasis>
constraint를 생성시키는데 사용되는 SQL 표현식.
</para>
</callout>
<callout arearefs="class19">
<para>
<literal>rowid</literal> (옵션): Hibernate는 지원되는 데이터베이스들, 예를 들어 Oracle 상에서 이른바
ROWID들을 사용할 수 있고, Hibernate는 당신이 이 옵션을 <literal>rowid</literal>로 설정하는 경우에 빠른
업데이트를 위한 특별한 <literal>rowid</literal> 컬럼을 사용할 수 있다. ROWID는 구현 상세이고 저장된
튜플(tuple)의 물리적이니 위치를 표현한다.
</para>
</callout>
<callout arearefs="class20">
<para>
<literal>subselect</literal> (옵션): 불변의 읽기 전용 엔티티를 데이터베이스 subselect로 매핑시킨다.
당신이 기본 테이블 대신에 뷰를 갖고자 원할 경우에 유용하지만, 사용을 자제하라. 추가 정보는 아래를 보라.
</para>
</callout>
<callout arearefs="class21">
<para>
<literal>abstract</literal> (옵션): <literal>&lt;union-subclass&gt;</literal> 계층 구조들 내에서
abstract 슈퍼클래스들을 마크하는데 사용된다.
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
명명된 영속 클래스가 인터페이스가 되는 것은 완전히 수용가능하다. 그런 다음 당신은 <literal>&lt;subclass&gt;</literal>
요소를 사용하여 그 인터페이스에 대한 구현 클래스들을 선언할 것이다. 당신은 임의의 <emphasis>static</emphasis> inner
클래스를 영속화 시킬 수 있다. 당신은 표준 형식, 예를 들어 <literal>eg.Foo$Bar</literal>를 사용하여 클래스 이름을
지정해야 한다.
</para>
<para>
불변의 클래스, <literal>mutable="false"</literal>는 어플리케이션에 의해 업데이트되지 않을 것이거나 삭제되지 않을 것이다.
이것은 Hibernate로 하여금 어떤 마이너 퍼포먼스 최적화를 행하게끔 허용해준다.
</para>
<para>
선택적인 <literal>proxy</literal> 속성은 그 클래스의 영속 인스턴스들에 대한 lazy 초기화를 가능하게 해준다. Hibernate는
명명된 인터페이스를 구현하는 CGLIB 프락시들을 초기에 반환할 것이다. 실제 영속 객체는 프락시의 메소드가 호출될 때 로드될 것이다.
아래 "Lazy 초기화를 위한 프락시들"을 보라.
</para>
<para><emphasis>Implicit</emphasis> 다형성은 클래스의 인스턴스들이 어떤 서브클래스나 구현된 인터페이스 또는 클래스를 명명하는
질의에 의해 반환될 것임을 의미하고 그 클래스의 어떤 서브클래스에 대한 인스턴스들이 그 클래스 자체를 명명하는 질의에 의해 반환될 것임을
의미한다. <emphasis>Explicit</emphasis> 다형성은 클래스 인스턴스들이 그 클래스를 명시적으로 명명하는 질의들에 의해서만
반환될 것임을 의미고 그 클래스를 명명하는 질의들이 이 <literal>&lt;class&gt;</literal> 선언 내부에서 <literal>&lt;subclass&gt;</literal>
또는 <literal>&lt;joined-subclass&gt;</literal>로 매핑된 서브 클래스들의 인스턴스들 만을 반환하게 될 것임을 의미한다.
대부분의 용도로, 디폴트인 <literal>polymorphism="implicit"</literal>가 적절하다.두 개의 다른 클래스들이 동일한 테이블로
매핑될 때 Explicit 다형성이 유용하다(이것은 테이블 컬럼들의 서브셋을 포함하는 "경량급" 클래스를 허용한다).
</para>
<para>
<literal>persister</literal> 속성은 클래스에 사용되는 영속화 방도를 당신이 커스트마이징 할 수 있도록 해준다. 예를 들어
당신은 <literal>org.hibernate.persister.EntityPersister</literal>에 대한 당신 자신의 서브클래스를 지정할 수도
있거나 당신은 심지어 예를 들어 플랫 파일들이나 LDAP로의 직렬화,내장 프로시저 호출들을 통해 영속화를 구현하는 인터페이스
<literal>org.hibernate.persister.ClassPersister</literal>에 대한 완전히 새로운 구현을 제공할 수도 있다.
(<literal>Hashtable</literal>로의 "영속성"에 관한) 간단한 예제는
<literal>org.hibernate.test.CustomPersister</literal>를 보라.
</para>
<para>
<literal>dynamic-update</literal> 설정과 <literal>dynamic-insert</literal> 설정은 서브클래스들에 의해
상속되지 않고 따라서 또한 <literal>&lt;subclass&gt;</literal> 또는 <literal>&lt;joined-subclass&gt;</literal>
요소들 상에 지정될 수도 있음을 노트하라. 이들 설정들은 몇몇 경우들에서 퍼포먼스를 증가시키지만 다른 경우들에서는 퍼포먼스를
실제로 감소시킬 수도 있다. 적절하게 사용하라.
</para>
<para>
<literal>select-before-update</literal> 사용은 대개 퍼포먼스를 감소시킬 것이다. 당신이 detached 인스턴스들의
그래프를 <literal>Session</literal>에 다시 첨부할 경우에 그것은 데이터베이스 업데이트 트리거가 불필요하게 호출되는
것을 방지하는데 매우 유용하다.
</para>
<para>
<literal>dynamic-update</literal>를 사용가능하게 할 경우, 당신은 다음 optimistic 잠금 전략들을 선택하게 될 것이다:
</para>
<itemizedlist>
<listitem>
<para>
<literal>version</literal>은 version/timestamp 컬럼들을 체크한다
</para>
</listitem>
<listitem>
<para>
<literal>all</literal>은 모든 컬럼들을 체크한다
</para>
</listitem>
<listitem>
<para>
<literal>dirty</literal>는 몇몇 동시성 업데이트들을 허용하여, 변경된 컬럼들을 체크한다
</para>
</listitem>
<listitem>
<para>
<literal>none</literal>은 optimistic 잠금을 사용하지 않는다
</para>
</listitem>
</itemizedlist>
<para>
우리는 당신이 Hibernate에서 optimistic 잠금을 위해 version/timestamp 컬럼들을 사용할 것을 <emphasis>매우</emphasis> 강력하게
권장한다. 이것은 퍼포먼스에 대해 최적의 방도이고 detached 인스턴스들에 대해 행해진 변경들을 정확하게 핸들링하는 유일한 방도이다(예를 들어
<literal>Session.merge()</literal>가 사용될 때).
</para>
<para>
Hibernate 매핑의 경우에 베이스 테이블과 뷰 사이에 차이점이 존재하지 않는다. 왜냐하면 이것이 데이터베이스 레벨에서는 투명하다고 기대되기
때문이다(몇몇 DBMS는 뷰를 고유하게 지원하지 않고 특히 뷰 업데이트를 지원하지 않음을 노트하라). 때때로 당신이 뷰를 사용하고자 원하지만,
(예를 들어 리거시 스키마로) 데이터베이스 속에 뷰를 생성시킬 수 없다. 이 경우에, 당신은 불변의 읽기 전용 엔티티를 주어진 SQL subselect
표현식으로 매핑시킬 수 있다:
</para>
<programlisting><![CDATA[<class name="Summary">
<subselect>
select item.name, max(bid.amount), count(*)
from item
join bid on bid.item_id = item.id
group by item.name
</subselect>
<synchronize table="item"/>
<synchronize table="bid"/>
<id name="name"/>
...
</class>]]></programlisting>
<para>
auto-flush가 정확하게 발생하도록 하고, 그리고 파생된 엔티티에 대한 질의들이 쓸효성 없는 데이터를 반환하지 않도록 함으로써, 이 엔티티와 동기화 될
테이블을 선언하라. <literal>&lt;subselect&gt;</literal>는 속성과 내포된 매핑 요소 양자로서 이용 가능하다.
</para>
</sect2>
<sect2 id="mapping-declaration-id" revision="4">
<title>id</title>
<para>
매핑된 클래스들은 데이터베이스 테이블의 프라이머리 키 컬럼을 선언<emphasis>해야 한다</emphasis>. 대부분의 클래스들은 또한 인스턴스의 유일 식별자를 소유하는
자바빈즈-스타일 프로퍼티를 가질 것이다. <literal>&lt;id&gt;</literal> 요소는 그 프로퍼티로부터 프라이머리 키 컬럼으로의 매핑을 정의한다.
</para>
<programlistingco>
<areaspec>
<area id="id1" coords="2 70"/>
<area id="id2" coords="3 70" />
<area id="id3" coords="4 70"/>
<area id="id4" coords="5 70" />
<area id="id5" coords="6 70" />
</areaspec>
<programlisting><![CDATA[<id
name="propertyName"
type="typename"
column="column_name"
unsaved-value="null|any|none|undefined|id_value"
access="field|property|ClassName">
node="element-name|@attribute-name|element/@attribute|."
<generator class="generatorClass"/>
</id>]]></programlisting>
<calloutlist>
<callout arearefs="id1">
<para>
<literal>name</literal> (옵션): 식별자 프로퍼티의 이름.
</para>
</callout>
<callout arearefs="id2">
<para>
<literal>type</literal> (옵션): Hibernate 타입을 나타내는 이름.
</para>
</callout>
<callout arearefs="id3">
<para>
<literal>column</literal> (옵션 - 디폴트는 프로퍼티 이름): 프라이머리 키 컬럼의 이름.
</para>
</callout>
<callout arearefs="id4">
<para>
<literal>unsaved-value</literal> (옵션 - 디폴트는 "sensible" 값):
이전 세션에서 저장되었거나 로드되었던 detached(분리된) 인스턴스들로부터 그것을 구분지우도록, 인스턴스가 새로이 초기화되어 있음(저장되어
있지 않음)을 나타내는 식별자 프로퍼티 값.
</para>
</callout>
<callout arearefs="id5">
<para>
<literal>access</literal> (옵션 - 디폴트는 <literal>property</literal>):
Hibernate가 프로퍼티 값에 액세스하는데 사용할 방도.
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
<literal>name</literal> 속성이 누락되면, 클래스는 식별자 프로퍼티를 갖지 않는다고 가정된다.
</para>
<para>
<literal>unsaved-value</literal> 속성은 Hibernate3에서는 거의 필요하지 않다.
</para>
<para>
composite 키들로서 리거시 데이터에 액세스하는 것을 허용해주는 대체적인 <literal>&lt;composite-id&gt;</literal>
선언이 존재한다. 우리는 그 밖의 어떤것에 대한 그것의 사용에 대해 강력하게 반대한다.
</para>
<sect3 id="mapping-declaration-id-generator" revision="2">
<title>Generator</title>
<para>
선택적인 <literal>&lt;generator&gt;</literal> 자식 요소는 영속 클래스의 인스턴스들에 대한 유일 식별자들을 생성시키는데 사용되는
자바 클래스를 명명한다. 만일 임의의 파라미터들이 생성기 인스턴스를 구성하거나 초기화 시키는데 필요할 경우, 그것들은 <literal>&lt;param&gt;</literal>
요소 를 사용하여 전달된다.
</para>
<programlisting><![CDATA[<id name="id" type="long" column="cat_id">
<generator class="org.hibernate.id.TableHiLoGenerator">
<param name="table">uid_table</param>
<param name="column">next_hi_value_column</param>
</generator>
</id>]]></programlisting>
<para>
모든 생성기들은 <literal>org.hibernate.id.IdentifierGenerator</literal> 인터페이스를 구현한다. 이것은 매우 간단한 인터페이스이다;
몇몇 어플리케이션들은 그것들 자신의 특화된 구현들을 제공하도록 선택할 수 있다. 하지만 Hibernate는 미리 빈드된 구현들의 영역들을 제공한다.
빌드-인 생성기(generator)들에 대한 단축 이름들이 존재한다:
<variablelist>
<varlistentry>
<term><literal>increment</literal></term>
<listitem>
<para>
동일한 테이블 속으로 데이터를 입력하는 다른 프로세스가 없을 때에만 유일한 <literal>long</literal>, <literal>short</literal> 또는 <literal>int</literal>
타입의 식별자들을 생성시킨다. <emphasis>클러스터 내에서는 사용하지 말라.</emphasis>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>identity</literal></term>
<listitem>
<para>
DB2, MySQL, MS SQL Server, Sybase, HypersonicSQL에서 식별 컬럼들을 지원한다. 반환되는 식별자는 <literal>long</literal>,
<literal>short</literal> 또는 <literal>int</literal> 타입이다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>sequence</literal></term>
<listitem>
<para>
DB2, PostgreSQL, Oracle, SAP DB, McKoi에서 시퀀스를 사용하거나 Interbase에서 생성기(generator)를 사용한다. 반환되는 식별자는
<literal>long</literal>, <literal>short</literal> 또는 <literal>int</literal> 타입이다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>hilo</literal></term>
<listitem>
<para id="mapping-declaration-id-hilodescription" revision="1">
테이블과 컬럼(디폴트로 각각 <literal>hibernate_unique_key</literal><literal>next_hi</literal>)이 hi 값들의
소스로서 주어지면, <literal>long</literal>, <literal>short</literal> 또는 <literal>int</literal> 타입의
식별자들을 효과적으로 생성시키는데 hi/lo 알고리즘을 사용한다. hi/lo 알고리즘은 특정 데이터베이스에 대해서만 유일한 식별자들을
생성시킨다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>seqhilo</literal></term>
<listitem>
<para>
명명된 데이터베이스 시퀀스가 주어지면, <literal>long</literal>, <literal>short</literal> 또는 <literal>int</literal>
타입의 식별자들을 효과적으로 생성시키는데 hi/lo 알고리즘을 사용한다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>uuid</literal></term>
<listitem>
<para>
네트웍 내에서 유일한(IP 주소가 사용된다) string 타입의 식별자들을 생성시키기 위해 128 비트 UUID 알고리즘을 사용한다.
UUID는 길이가 32인 16진수들의 문자열로서 인코딩 된다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>guid</literal></term>
<listitem>
<para>
MS SQL Server와 MySQL 상에서 데이터베이스 생성 GUID 문자열을 사용한다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>native</literal></term>
<listitem>
<para>
기본 데이터베이스의 가용성들에 의존하여 <literal>identity</literal>, <literal>sequence</literal>
또는 <literal>hilo</literal>를 찾아낸다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>assigned</literal></term>
<listitem>
<para>
어플리케이션으로 하여금 <literal>save()</literal>가 호출되기 전에 식별자를 객체에 할당하도록 한다.
<literal>&lt;generator&gt;</literal> 요소가 지정되지 않을 경우 이것이 디폴트 방도이다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>select</literal></term>
<listitem>
<para>
어떤 유일 키에 의해 행을 select하고 프라이머리 키 값을 검색함으로써 데이터베이스 트리거에 의해 할당된
프라이머리 키를 검색한다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>foreign</literal></term>
<listitem>
<para>
또 다른 연관된 객체의 식별자를 사용한다. 대개 <literal>&lt;one-to-one&gt;</literal> 프라이머리 키
연관관계와 함께 사용된다.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</sect3>
<sect3 id="mapping-declaration-id-hilo" revision="1">
<title>Hi/lo algorithm</title>
<para>
<literal>hilo</literal><literal>seqhilo</literal> 생성기들은 식별자 생성에 대한 마음에 드는 접근법인,
hi/lo 알고리즘에 대한 두 개의 대체 구현들은 제공한다. 첫 번째 구현은 다음에 이용 가능한 "hi" 값을 수용하기 위한 "특별한"
데이터베이스 테이블을 필요로 한다. 두 번째는 (지원되는) Oracle 스타일의 시퀀스를 사용한다.
</para>
<programlisting><![CDATA[<id name="id" type="long" column="cat_id">
<generator class="hilo">
<param name="table">hi_value</param>
<param name="column">next_value</param>
<param name="max_lo">100</param>
</generator>
</id>]]></programlisting>
<programlisting><![CDATA[<id name="id" type="long" column="cat_id">
<generator class="seqhilo">
<param name="sequence">hi_value</param>
<param name="max_lo">100</param>
</generator>
</id>]]></programlisting>
<para>
불행히도 당신은 Hibernate에 당신 자신의 <literal>Connection</literal>을 제공할 때 <literal>hilo</literal>
사용할 수 없다. Hibernate가 JTA의 도움을 받는 커넥션들을 얻기 위해 어플리케이션 서버 데이터소스를 사용할 때 당신은
<literal>hibernate.transaction.manager_lookup_class</literal>를 적절하게 구성해야 한다.
</para>
</sect3>
<sect3 id="mapping-declaration-id-uuid">
<title>UUID 알고리즘</title>
<para>
UUID 는 다음을 포함한다: IP 주소, JVM의 시작 시간(정확히 1/4 초), 시스템 시간과 (JVM 내에서 유일한) counter 값.
Java 코드로부터 MAC 주소 또는 메모리 주소를 얻는 것은 불가능하여서, 이것은 우리가 JNI를 사용하지 않고서 행할 수 있는
최상의 것이다.
</para>
</sect3>
<sect3 id="mapping-declaration-id-sequences">
<title>식별 컬럼들과 시퀀스들</title>
<para>
식별 컬럼들을 지원하는 데이터베이스들(DB2, MySQL, Sybase, MS SQL)의 경우, 당신은 <literal>identity</literal>
생성을 사용할 수 있다. 시퀀스들을 지원하는 데이터베이스들(DB2, Oracle, PostgreSQL, Interbase, McKoi, SAP DB)의
경우, 당신은 <literal>sequence</literal> 스타일 키 생성을 사용할 수도 있다. 이들 방도들 모두 새로운 객체를 insert하기
위해 두 개의 SQL 질의들을 필요로 한다.
</para>
<programlisting><![CDATA[<id name="id" type="long" column="person_id">
<generator class="sequence">
<param name="sequence">person_id_sequence</param>
</generator>
</id>]]></programlisting>
<programlisting><![CDATA[<id name="id" type="long" column="person_id" unsaved-value="0">
<generator class="identity"/>
</id>]]></programlisting>
<para>
크로스 플랫폼 개발을 위해서, <literal>native</literal> 방도가 기준 데이터베이스들의 가용성들에 따라 <literal>identity</literal>,
<literal>sequence</literal>, <literal>hilo</literal> 방도 중에서 선택될 것이다.
</para>
</sect3>
<sect3 id="mapping-declaration-id-assigned">
<title>할당된 식별자들</title>
<para>
(Hibernate로 하여금 식별자들을 생성시키도록 하는 것과는 반대로) 당신이 어플리케이션으로 하여금 식별자들을 할당하도록 원할 경우,
당신은 <literal>assigned</literal> 생성기를 사용할 수 있다. 이 특별한 생성기는 객체의 identifier 프로퍼티에 이미 할당된
식별자 값을 사용할 것이다. 이 생성기(generator)는 프라이머리 키가 대용(surrogate ) 키 대신에 natural 키일 때 사용된다.
당신이 <literal>&lt;generator&gt;</literal> 요소를 지정하지 않을 경우에 이것이 디폴트 특징이다
</para>
<para>
<literal>assigned</literal> 생성기(generator)를 선택하는 것은 , version 또는 timestamp 프로퍼티가 존재하지 않는 한
또는 당신이 <literal>Interceptor.isUnsaved()</literal>를 정의하지 않는 한, 하나의 인스턴스가 transient 또는 detached인지를
결정하기 위해 Hibernae로 하여금 데이터베이스에 접촉하도록 강제하는, <literal>unsaved-value="undefined"</literal>
Hibernate에게 사용하도록 한다.
</para>
</sect3>
<sect3 id="mapping-declaration-id-select">
<title>트리거들에 의해 할당된 프라이머리 키들</title>
<para>
리거시 스키마에 대해서만(Hibernate는 트리거들을 가진 DDL을 생성시키지 않는다).
</para>
<programlisting><![CDATA[<id name="id" type="long" column="person_id">
<generator class="select">
<param name="key">socialSecurityNumber</param>
</generator>
</id>]]></programlisting>
<para>
위의 예제에서, natural 키로서 클래스에 의해 <literal>socialSecurityNumber</literal>로 명명된 유일 값을 가진 프로퍼티가 존재하고,
트리거에 의해 그 값이 생성되는 <literal>person_id</literal>로 명명된 대용키가 존재한다.
</para>
</sect3>
</sect2>
<sect2 id="mapping-declaration-compositeid" revision="3">
<title>composite-id</title>
<programlisting><![CDATA[<composite-id
name="propertyName"
class="ClassName"
mapped="true|false"
access="field|property|ClassName">
node="element-name|."
<key-property name="propertyName" type="typename" column="column_name"/>
<key-many-to-one name="propertyName class="ClassName" column="column_name"/>
......
</composite-id>]]></programlisting>
<para>
composite 키를 가진 테이블의 경우, 당신은 클래스의 여러 프로퍼티들을 식별자 프로퍼티들로서 매핑할 수 있다.
<literal>&lt;composite-id&gt;</literal> 요소는 자식 요소들로서 <literal>&lt;key-property&gt;</literal>
프로퍼티 매핑과 <literal>&lt;key-many-to-one&gt;</literal> 매핑들을 허용한다.
</para>
<programlisting><![CDATA[<composite-id>
<key-property name="medicareNumber"/>
<key-property name="dependent"/>
</composite-id>]]></programlisting>
<para>
당신의 영속 클래스는 composite 식별자 동등성을 구현하기 위해서 <literal>equals()</literal>
<literal>hashCode()</literal>를 오버라이드 <emphasis>시켜야 한다</emphasis>. 그것은 또한
<literal>Serializable</literal>을 구현해야 한다.
</para>
<para>
불행히도, composite 식별자들에 대한 이 접근법은 영속 객체가 그것 자신의 식별자라는 점을 의미한다. 객체
자신 외의 다른 "핸들"이 존재하지 않는다. 당신은 당신이 composite key로 연관된 영속 상태를 <literal>load()</literal>
할 수 있기 이전에 영속 클래스 그 자체의 인스턴스를 초기화 하고 그것의 식별자 프로퍼티들을 군집화 시켜야 한다. 우리는
이 접근법을 <emphasis>embedded</emphasis> composite 식별자로 부르고, 중대한 어플리케이션들에 대해 그것을 억제시킨다.
</para>
<para>
두 번째 접근법은 우리가 <emphasis>mapped</emphasis> composite 식별자라고 부르는 것인데, 여기서
<literal>&lt;composite-id&gt;</literal> 요소 내에 명명된 여기서 식별자 프로퍼티들은 영속 클래스와 별도의 식별자 클래스
양자 상에 중복된다.
</para>
<programlisting><![CDATA[<composite-id class="MedicareId" mapped="true">
<key-property name="medicareNumber"/>
<key-property name="dependent"/>
</composite-id>]]></programlisting>
<para>
이 예제에서, composite 식별자 클래스인 <literal>MedicareId</literal>와 엔티티 크래스 그 자체 양자는
<literal>medicareNumber</literal><literal>dependent</literal>로 명명된 프로퍼티들을 갖는다. 식별자 클래스는
<literal>equals()</literal><literal>hashCode()</literal>를 오버라이드 시켜고 <literal>Serializable</literal>
구현해야 한다. 이 접근법의 단점은 아주 명백한&mdash;코드 중복이다.
</para>
<para>
다음 속성들은 매핑된 composite 식별자를 지정하는데 사용된다:
</para>
<itemizedlist spacing="compact">
<listitem>
<para>
<literal>mapped</literal> (옵션, 디폴트는 <literal>false</literal>):
하나의 매핑된 composite 식별자가 사용됨을, 그리고 포함된 프로퍼티 매핑들이 엔티티 클래스와
composite 식별자 클래스 양자를 참조함을 나타낸다.
</para>
</listitem>
<listitem>
<para>
<literal>class</literal> (옵션, 하지만 하나의 매핑된 commposite 식별자에 대해서는 필수적임):
하나의 composite 식별자로서 사용되는 클래스.
</para>
</listitem>
</itemizedlist>
<para>
우리는 <xref linkend="components-compositeid"/>에서 composite 식별자가 하나의 component 클래스로서 구현되는
보다 편리한 접근법인 세번째 방도를 설명할 것이다. 아래에 설명되어 있는 속성들은 이 대체적인 접근법에만 적용된다:
</para>
<itemizedlist spacing="compact">
<listitem>
<para>
<literal>name</literal> (옵션, 이 접근법의 경우에는 필수임): 하나의 component
식별자를 소유하는 컴포넌트 타입의 프로퍼티(9장을 보라).
</para>
</listitem>
<listitem>
<para>
<literal>access</literal> (옵션 - 디폴트는 <literal>property</literal>):
Hibernate가 프로퍼티 값에 접근하는데 사용할 방도.
</para>
</listitem>
<listitem>
<para>
<literal>class</literal> (옵션 - 디폴트는 reflection에 의해 결정된 프로퍼티 타입):
하나의 composite 식별자로서 사용되는 컴포넌트 클래스(다음 절을 보라).
</para>
</listitem>
</itemizedlist>
<para>
이 세번째 접근법, <emphasis>identifier component</emphasis>은 거의 모든 어플리케이션들에 대해 우리가 권장하는 것이다.
</para>
</sect2>
<sect2 id="mapping-declaration-discriminator" revision="3">
<title>discriminator</title>
<para>
<literal>&lt;discriminator&gt;</literal> 요소는 table-per-class-hierarchy(테이블 당 클래스 계층구조)
매핑 방도를 사용하는 다형성 영속화에 필요하고 테이블의 discriminator(판별자) 컬럼을 선언한다. discriminator 컬럼은
특정 행에 대해 초기화 시킬 서브 클래스가 무엇인지를 영속 계층에 알려주는 표시자 값들을 포함한다. 타입들의 제한적인 집합이
사용될 수 있다: <literal>string</literal>, <literal>character</literal>, <literal>integer</literal>,
<literal>byte</literal>, <literal>short</literal>, <literal>boolean</literal>,
<literal>yes_no</literal>, <literal>true_false</literal>.
</para>
<programlistingco>
<areaspec>
<area id="discriminator1" coords="2 60"/>
<area id="discriminator2" coords="3 60" />
<area id="discriminator3" coords="4 60" />
<area id="discriminator4" coords="5 60" />
<area id="discriminator5" coords="6 60" />
</areaspec>
<programlisting><![CDATA[<discriminator
column="discriminator_column"
type="discriminator_type"
force="true|false"
insert="true|false"
formula="arbitrary sql expression"
/>]]></programlisting>
<calloutlist>
<callout arearefs="discriminator1">
<para>
<literal>column</literal> (옵션 - 디폴트는 <literal>class</literal>)
discriminator 컬럼명.
</para>
</callout>
<callout arearefs="discriminator2">
<para>
<literal>type</literal> (옵션 - 디폴트는 <literal>string</literal>)
Hibernate 타입을 나타내는 이름
</para>
</callout>
<callout arearefs="discriminator3">
<para>
<literal>force</literal> (옵션 - 디폴트는 <literal>false</literal>)
이것은 Hibernate로 하여금 루트 클래스의 모든 인스턴스들을 검색할 때조차도 허용된 discriminator
값들을 지정하도록 "강제한다".
</para>
</callout>
<callout arearefs="discriminator4">
<para>
<literal>insert</literal> (옵션 - 디폴트는 <literal>true</literal>)
당신의 discriminator 컬럼이 또한 매핑된 composite 식별자의 부분일 경우에 이것을 <literal>false</literal>로 설정하라.
(Hibernate에게 SQL <literal>INSERT</literal>들 속에 그 컬럼을 포함하지 않도록 통보한다.)
</para>
</callout>
<callout arearefs="discriminator5">
<para>
<literal>formula</literal> (옵션)
타입이 평가 되어야 할 때 실행되는 임의의 SQL 표현식. 컨텐츠 기반의 판별을 허용해준다.
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
discriminator 컬럼의 실제 값들은 <literal>&lt;class&gt;</literal> 요소와
<literal>&lt;subclass&gt;</literal> 요소의 <literal>discriminator-value</literal> 속성에 의해 지정된다.
</para>
<para>
<literal>force</literal> 속성은 테이블이 영속 클래스로 매핑되지 않는 "특별한" discriminator 값들을 가진 행들을
포함할 경우에(만) 유용하다. 이것은 대개 그 경우가 아닐 것이다.
</para>
<para>
<literal>formula</literal> 속성을 사용하여 당신은 행의 타입을 판단하는데 사용될 임의의 SQL 표현식을 선언할 수 있다:
</para>
<programlisting><![CDATA[<discriminator
formula="case when CLASS_TYPE in ('a', 'b', 'c') then 0 else 1 end"
type="integer"/>]]></programlisting>
</sect2>
<sect2 id="mapping-declaration-version" revision="4">
<title>version (옵션)</title>
<para>
<literal>&lt;version&gt;</literal> 요소는 옵션이고 테이블이 버전화된 데이터를 포함한다는 것을 나타낸다.
이것은 당신이 <emphasis>긴 트랜잭션(long transaction)들</emphasis>을 사용할 계획이라면 특히 유용하다
(아래를 보라).
</para>
<programlistingco>
<areaspec>
<area id="version1" coords="2 70"/>
<area id="version2" coords="3 70"/>
<area id="version3" coords="4 70"/>
<area id="version4" coords="5 70"/>
<area id="version5" coords="6 70"/>
<area id="version6" coords="7 70"/>
<area id="version7" coords="8 70"/>
</areaspec>
<programlisting><![CDATA[<version
column="version_column"
name="propertyName"
type="typename"
access="field|property|ClassName"
unsaved-value="null|negative|undefined"
generated="never|always"
insert="true|false"
node="element-name|@attribute-name|element/@attribute|."
/>]]></programlisting>
<calloutlist>
<callout arearefs="version1">
<para>
<literal>column</literal> (옵션 - 디폴트는 프로퍼티 명):
버전 번호를 가진 컬럼의 이름.
</para>
</callout>
<callout arearefs="version2">
<para>
<literal>name</literal>: 영속 클래스의 프로퍼티 명.
</para>
</callout>
<callout arearefs="version3">
<para>
<literal>type</literal> (옵션 - 디폴트는 <literal>integer</literal>):
버전 번호의 타입.
</para>
</callout>
<callout arearefs="version4">
<para>
<literal>access</literal> (옵션 - 디폴트는 <literal>property</literal>):
Hibernate가 프로퍼티 값에 액세스하는데 사용할 방도.
</para>
</callout>
<callout arearefs="version5">
<para>
<literal>unsaved-value</literal> (옵션 - 디폴트는 <literal>undefined</literal>):
이전 세션에서 저장되었거나 로드되었던 detached 인스턴스로부터 구별지어서, 인스턴스가 새로이 초기화됨(unsaved)을
나타내는 version 프로퍼티 값.(<literal>undefined</literal>는 식별자 프로퍼티 값이 사용될 것임을 지정한다.)
</para>
</callout>
<callout arearefs="version6">
<para>
<literal>generated</literal> (옵션 - 디폴트는 <literal>never</literal>):
이 version 프로퍼티 값이 데이터베이스에 의해 실제로 산출되는지를 지정한다.
<xref linkend="mapping-generated">산출되는 프로퍼티들</xref>에 관한 논의를 보라.
</para>
</callout>
<callout arearefs="version7">
<para>
<literal>insert</literal> (옵션 - 디폴트는 <literal>true</literal>):
version 컬럼이 SQL insert 문장들 속에 포함될 것인지 여부를 지정한다.
데이터베이스 컬럼이 디폴트 값 <literal>0</literal>으로 정의되는 경우에만 <literal>false</literal>
설정될 수 있다.
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
버전 번호들은 <literal>long</literal>, <literal>integer</literal>, <literal>short</literal>,
<literal>timestamp</literal> 또는 <literal>calendar</literal> 타입일 수 있다.
</para>
<para>
version 또는 timestamp 프로퍼티는 detached 인스턴스에 대해 결코 null일 수가 없어서, Hibernate는
다른 <literal>unsaved-value</literal> 방도들이 지정되는 것에 상관없이, null version이나 timestamp를
가진 임의의 인스턴스를 transient로서 검출할 것이다. <emphasis>null 허용되는 version 이나 property를
선언하는 것은 Hibernate에서 transitive reattachment에 대한 임의의 문제들을 피하는 쉬운 방법이고,
assigned 식별자들이나 composite key들을 사용하는 사람들에게 특히 유용하다!</emphasis>
</para>
</sect2>
<sect2 id="mapping-declaration-timestamp" revision="3" >
<title>timestamp (옵션)</title>
<para>
옵션 <literal>&lt;timestamp&gt;</literal> 요소는 테이블이 타임스탬프화 된 데이터를 포함함을 나타낸다. 이것은
버전화에 대한 대체물로서 고안되었다. Timestamp은 고유하게 optimistic 잠금에 대한 다소 안전한 구현이다. 하지만 때때로
어플리케이션은 다른 방법들로 timestamp들을 사용할 수도 있다.
</para>
<programlistingco>
<areaspec>
<area id="timestamp1" coords="2 70"/>
<area id="timestamp2" coords="3 70" />
<area id="timestamp3" coords="4 70" />
<area id="timestamp4" coords="5 70" />
<area id="timestamp5" coords="6 70" />
<area id="timestamp6" coords="7 70" />
</areaspec>
<programlisting><![CDATA[<timestamp
column="timestamp_column"
name="propertyName"
access="field|property|ClassName"
unsaved-value="null|undefined"
source="vm|db"
generated="never|always"
node="element-name|@attribute-name|element/@attribute|."
/>]]></programlisting>
<calloutlist>
<callout arearefs="timestamp1">
<para>
<literal>column</literal> (옵션 - 디폴트는 프로퍼티 명):
타임스탬프를 포함하는 컬럼 명.
</para>
</callout>
<callout arearefs="timestamp2">
<para>
<literal>name</literal>:
영속 클래스에 대해 자바 <literal>Date</literal> 또는 <literal>Timestamp</literal> 타입을
가진 자바빈즈 스타일의 프로퍼티 이름.
</para>
</callout>
<callout arearefs="timestamp3">
<para>
<literal>access</literal> (옵션 - 디폴트는 <literal>property</literal>):
Hibernate가 프로퍼티 값에 접근하는데 사용할 방도.
</para>
</callout>
<callout arearefs="timestamp4">
<para>
<literal>unsaved-value</literal> (옵션 - 디폴트는 <literal>null</literal>):
이전 세션에서 저장되었거나 로드되었던 detached 인스턴스로부터 인스턴스를 구별지우는, 인스턴스가 새로이
초기화됨(unsaved)을 나타내는 version 프로퍼티 값.(<literal>undefined</literal>는 식별자
프로퍼티 값이 사용될 것임을 지정한다.)
</para>
</callout>
<callout arearefs="timestamp5">
<para>
<literal>source</literal> (옵션 - 디폴트는 <literal>vm</literal>):
Hibernate는 어느 장소로부터 timestamp 값을 검색할 것인가? 데이터베이스로부터인가 현재의 JVM으로부터인가?
Hibernate가 "다음 값"을 결정하기 위해 데이터베이스에 접속해야 하기 때문에 데이터베이스 기반의
timestamp들은 오버헤드를 초래하지만, 클러스터링된 환경들의 용도로 더 안전할 것이다. 또한 모든
<literal>Dialect</literal>들이 데이터베이스의 현재의 timestamp에 대한 검색을 지원하는 것으로 알려져
있는 반면에, 다른 <literal>Dialect</literal>들은 정밀도 결핍 때문에 잠금에 있어 사용에 대해 안전하지 않을
수 있음을 노트하라(예를 들면 오라클 8).
</para>
</callout>
<callout arearefs="timestamp6">
<para>
<literal>generated</literal> (옵션 - 디폴트는 <literal>never</literal>):
이 timestamp 프로퍼티 값이 데이터베이스에 의해 실제로 산출되는지를 지정한다.
<xref linkend="mapping-generated">산출되는 프로퍼티들</xref>에 대한 논의들 보라.
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
<literal>&lt;timestamp&gt;</literal><literal>&lt;version type="timestamp"&gt;</literal>
같음을 노트하라. 그리고 <literal>&lt;timestamp use-db="true"&gt;</literal>
<literal>&lt;version type="dbtimestamp"&gt;</literal>과 같다
</para>
</sect2>
<sect2 id="mapping-declaration-property" revision="4">
<title>프로퍼티</title>
<para>
<literal>&lt;property&gt;</literal> 요소는 클래스의 자바빈즈 스타일의 영속 프로퍼티를 선언한다.
</para>
<programlistingco>
<areaspec>
<area id="property1" coords="2 70"/>
<area id="property2" coords="3 70"/>
<area id="property3" coords="4 70"/>
<areaset id="property4-5" coords="">
<area id="property4" coords='5 70'/>
<area id="property5" coords='6 70'/>
</areaset>
<area id="property6" coords="7 70"/>
<area id="property7" coords="8 70"/>
<area id="property8" coords="9 70"/>
<area id="property9" coords="10 70"/>
<area id="property10" coords="11 70"/>
<area id="property11" coords="12 70"/>
<area id="property12" coords="13 70"/>
</areaspec>
<programlisting><![CDATA[<property
name="propertyName"
column="column_name"
type="typename"
update="true|false"
insert="true|false"
formula="arbitrary SQL expression"
access="field|property|ClassName"
lazy="true|false"
unique="true|false"
not-null="true|false"
optimistic-lock="true|false"
generated="never|insert|always"
node="element-name|@attribute-name|element/@attribute|."
index="index_name"
unique_key="unique_key_id"
length="L"
precision="P"
scale="S"
/>]]></programlisting>
<calloutlist>
<callout arearefs="property1">
<para>
<literal>name</literal>: 첫 소문자로 시작하는 프로퍼티 이름.
</para>
</callout>
<callout arearefs="property2">
<para>
<literal>column</literal> (옵션 - 디폴트는 프로퍼티 이름):
매핑된 데이터베이스 테이블 컬럼의 이름. 이것은 또한 내부에 포함되는 <literal>&lt;column&gt;</literal> 요소(들)에
의해 지정될 수도 있다.
</para>
</callout>
<callout arearefs="property3">
<para>
<literal>type</literal> (옵션): Hibernate 타입을 나타내는 이름.
</para>
</callout>
<callout arearefs="property4-5">
<para>
<literal>update, insert</literal> (옵션 - 디폴트는 <literal>true</literal>) :
매핑된 컬럼들이 <literal>UPDATE</literal>와/또는 <literal>INSERT</literal> 문장들속에 포함될 것임을 지정한다.
둘다 <literal>false</literal>로 설정하는 것은 그 값이 동일한 컬럼(들)로 매핑되는 어떤 다른 프로퍼티로부터 또는 트리거에
의해 또는 다른 어플리케이션으로부터 초기화 되는 순수하게 "파생된(derived)" 프로퍼티를 허용해준다.
</para>
</callout>
<callout arearefs="property6">
<para>
<literal>formula</literal> (옵션):
<emphasis>계산되는</emphasis> 프로퍼티에 대해 값을 정의하는 SQL 표현식. 계산되는 프로퍼티들은
그것들 자신에 대한 컬럼 매핑을 갖지 않는다.
</para>
</callout>
<callout arearefs="property7">
<para>
<literal>access</literal> (옵션 - 디폴트는 <literal>property</literal>):
Hibernate가 프로퍼티 값에 접근하는데 사용할 방도.
</para>
</callout>
<callout arearefs="property8">
<para>
<literal>lazy</literal> (옵션 - 디폴트는 <literal>false</literal>):
인스턴스 변수가 처음으로 액세스 될 때 이 프로퍼티가 lazily하게 페치될 것임을 지정한다(빌드-시 바이트코드
수단을 필요로 한다).
</para>
</callout>
<callout arearefs="property9">
<para>
<literal>unique</literal> (옵션):
컬럼들에 대한 유일 컨스트레인트의 DDL 생성을 가능하게 만든다. 또한 이것이 <literal>property-ref</literal>
타켓이 되는 것을 허용해준다.
</para>
</callout>
<callout arearefs="property10">
<para>
<literal>not-null</literal> (옵션):
컬럼들에 대해 null 가능 컨스트레인트의 DDL 생성을 가능하게 만든다.
</para>
</callout>
<callout arearefs="property11">
<para>
<literal>optimistic-lock</literal> (옵션 - 디폴트는 <literal>true</literal>):
이 프로퍼티에 대한 업데이트들이 optimistic 잠금을 획득하는 것을 필요로 하거나 필요로 하지 않음을 지정한다.
달리말해, 이 프로퍼티가 dirty일 때 버전 증가가 발생할 경우인지를 결정한다.
</para>
</callout>
<callout arearefs="property12">
<para>
<literal>generated</literal> (옵션 - 디폴트는 <literal>never</literal>):
이 프로퍼티 값이 데이터베이스에 의해 실제로 산출되는지를 지정한다.
<xref linkend="mapping-generated">산출되는 프로퍼티들</xref>에 대한 논의를 보라.
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
<emphasis>typename</emphasis>은 다음일 수 있다:
</para>
<orderedlist spacing="compact">
<listitem>
<para>
Hibernate 기본 타입의 이름 (예를 들어. <literal>integer, string, character, date, timestamp,
float, binary, serializable, object, blob</literal>).
</para>
</listitem>
<listitem>
<para>
디폴트 기본 타입을 가진 Java 클래스의 이름(예를 들어. <literal>int, float,
char, java.lang.String, java.util.Date, java.lang.Integer, java.sql.Clob</literal>).
</para>
</listitem>
<listitem>
<para>
serializable Java 클래스의 이름.
</para>
</listitem>
<listitem>
<para>
맞춤 타입의 클래스 이름(예를 들어. <literal>com.illflow.type.MyCustomType</literal>).
</para>
</listitem>
</orderedlist>
<para>
만일 당신이 타입을 지정하지 않을 경우, Hibernate는 정확한 Hibernate 타입을 추정하기 위해 명명된 프로퍼티에 대해
reflection을 사용할 것이다. Hibernate는 그 순서에서 2,3,4 규칙들을 사용하여 프로퍼티 getter의 반환 클래스의
이름을 해석하려고 시도할 것이다. 하지만 이것은 항상 충분하지는 않다. 어떤 경우들에서, 당신은 여전히 <literal>type</literal>
속성을 필요로 할 것이다.(예를 들어, <literal>Hibernate.DATE</literal><literal>Hibernate.TIMESTAMP</literal>
사이를 구별하기 위해, 또는 맞춤 타입을 지정하기 위해.)
</para>
<para>
<literal>access</literal> 속성은 당신으로 하여금 Hibernate가 런타임 시에 프로퍼티에 액세스하는 방법을 제어하도록 해준다.
디폴트로 Hibernate는 프로퍼티 get/set 쌍을 호출할 것이다. 만일 당신이 <literal>access="field"</literal>를 지정할
경우, Hibernate는 get/set 쌍을 피하고 reflection을 사용하여 직접 필드에 액세스 할 것이다. 당신은
<literal>org.hibernate.property.PropertyAccessor</literal> 인터페이스를 구현하는 클래스를 명명함으로써
프로퍼티 접근을 위한 당신 자신의 방도를 지정할 수도 있다.
</para>
<para>
특별히 강력한 특징은 파생된 플로퍼티들이다. 이들 프로퍼티들은 정의상 읽기 전용이고, 그 프로퍼티 값은 로드 시에 계산된다. 당신은
그 계산을 SQL 표현식으로 선언하고, 이것은 인스턴스를 로드시키는 SQL 질의 내의 <literal>SELECT</literal> 절 서브질의로
번역된다:
</para>
<programlisting><![CDATA[
<property name="totalPrice"
formula="( SELECT SUM (li.quantity*p.price) FROM LineItem li, Product p
WHERE li.productId = p.productId
AND li.customerId = customerId
AND li.orderNumber = orderNumber )"/>]]></programlisting>
<para>
당신은 특정 컬럼(주어진 예제에서는 <literal>customerId</literal>)에 대해 alias를 선언하지 않음으로써 엔티티들 자신의
테이블을 참조할 수 있음을 노트하라. 또한 당신은 만일 당신이 그 속성을 사용하고 싶지 않을 경우에 내포된 <literal>&lt;formula&gt;</literal>
매핑 요소를 사용할 수 있음을 노트하라.
</para>
</sect2>
<sect2 id="mapping-declaration-manytoone" revision="5">
<title>many-to-one</title>
<para>
또 다른 영속 클래스에 대한 정규 연관관계는 <literal>many-to-one</literal> 요소를 사용하여 선언된다. 관계형 모형은
many-to-one 연관관계이다.: 하나의 테이블 내에 있는 foreign 키는 대상 테이블의 프라이머리 키 컬럼(들)을 참조하고 있다.
</para>
<programlistingco>
<areaspec>
<area id="manytoone1" coords="2 70"/>
<area id="manytoone2" coords="3 70"/>
<area id="manytoone3" coords="4 70"/>
<area id="manytoone4" coords="5 70"/>
<area id="manytoone5" coords="6 70"/>
<areaset id="manytoone6-7" coords="">
<area id="manytoone6" coords='7 70'/>
<area id="manytoone7" coords='8 70'/>
</areaset>
<area id="manytoone8" coords="9 70"/>
<area id="manytoone9" coords="10 70"/>
<area id="manytoone10" coords="11 70"/>
<area id="manytoone11" coords="12 70"/>
<area id="manytoone12" coords="13 70"/>
<area id="manytoone13" coords="14 70"/>
<area id="manytoone14" coords="15 70"/>
<area id="manytoone15" coords="16 70"/>
<area id="manytoone16" coords="17 70"/>
</areaspec>
<programlisting><![CDATA[<many-to-one
name="propertyName"
column="column_name"
class="ClassName"
cascade="cascade_style"
fetch="join|select"
update="true|false"
insert="true|false"
property-ref="propertyNameFromAssociatedClass"
access="field|property|ClassName"
unique="true|false"
not-null="true|false"
optimistic-lock="true|false"
lazy="proxy|no-proxy|false"
not-found="ignore|exception"
entity-name="EntityName"
formula="arbitrary SQL expression"
node="element-name|@attribute-name|element/@attribute|."
embed-xml="true|false"
index="index_name"
unique_key="unique_key_id"
foreign-key="foreign_key_name"
/>]]></programlisting>
<calloutlist>
<callout arearefs="manytoone1">
<para>
<literal>name</literal>: 프로퍼티의 이름.
</para>
</callout>
<callout arearefs="manytoone2">
<para>
<literal>column</literal> (옵션):
foreign key 컬럼의 이름. 이것은 또한 내포된 <literal>&lt;column&gt;</literal> 요소(들)에 의해
지정된다.
</para>
</callout>
<callout arearefs="manytoone3">
<para>
<literal>class</literal> (옵션 - 디폴트는 reflection에 의해 결정된 프로퍼티 타입):
연관된 클래스의 이름.
</para>
</callout>
<callout arearefs="manytoone4">
<para>
<literal>cascade</literal> (옵션):
어느 오퍼레이션들이 부모 객체로부터 연관된 객체로 케스케이드 될 것인지를 지정한다.
</para>
</callout>
<callout arearefs="manytoone5">
<para>
<literal>fetch</literal> (옵션 - 디폴트는 <literal>select</literal>):
outer-join 페칭 또는 sequential select 페칭 사이에서 선택하라.
</para>
</callout>
<callout arearefs="manytoone6-7">
<para>
<literal>update, insert</literal> (옵션 - 디폴트는 <literal>true</literal>)
매핑된 컬럼들이 SQL <literal>UPDATE</literal>와/또는 <literal>INSERT</literal> 문장들 속에 포함될 것인지를 지정한다.
둘다 <literal>false</literal>로 설정하는 것은 그 값이 동일한 컬럼(들)로 매핑시키는 어떤 다른 컬럼들로부터 초기화 되거나 트리거나
다른 어플리케이션에 의해 초기화되는 단순한 "파생된" 연관관계 값을 허용한다.
</para>
</callout>
<callout arearefs="manytoone8">
<para>
<literal>property-ref</literal>: (옵션) 이 foreign key에 조인되는 연관된 클래스의 프로퍼티 이름. 지정되지 않을 경우,
연관 클래스의 프라이머리 키가 사용된다.
</para>
</callout>
<callout arearefs="manytoone9">
<para>
<literal>access</literal> (옵션 - 디폴트는 <literal>property</literal>):
Hibernate가 프로퍼티 값에 접근하는데 사용할 방도.
</para>
</callout>
<callout arearefs="manytoone10">
<para>
<literal>unique</literal> (옵션):
foreign-key 컬럼을 위한 유일 컨스트레인트의 DDL 생성을 가능하도록 해준다. 또한 이것이 property-ref의 대상이 되는 것을 허용해준다.
이것은 연관 다중성(association multiplicity)을 효율적으로 일 대 일로 만든다.
</para>
</callout>
<callout arearefs="manytoone11">
<para>
<literal>not-null</literal> (옵션):
foreign key 컬럼들을 위한 null 가능한 컨스트레인트의 DDL 생성을 가능하도록 해준다.
</para>
</callout>
<callout arearefs="manytoone12">
<para>
<literal>optimistic-lock</literal> (옵션 - 디폴트는 <literal>true</literal>):
이 프로퍼티에 대한 업데이트들이 optimistic lock의 획득을 필요로 하는지 아닌지 여부를 지정한다.
달리 말해 이 프로퍼티가 dirty일 때 version 증가가 발생해야 할 경우인지를 결정한다.
</para>
</callout>
<callout arearefs="manytoone13">
<para>
<literal>lazy</literal> (옵션 - 디폴트는 <literal>proxy</literal>):
디폴트로, 단일 포인트 연관들이 프락시된다. <literal>lazy="no-proxy"</literal>는 인스턴스 변수가 처음으로 접근될 때
그 프로퍼티가 lazily 페치될 것임을 지정한다(빌드-시 바이트코드 수단을 필요로 한다). <literal>lazy="false"</literal>
그 연관이 항상 eagerly 페치될 것임을 지정한다.
</para>
</callout>
<callout arearefs="manytoone14">
<para>
<literal>not-found</literal> (옵션 - 디폴트는 <literal>exception</literal>):
누락된 행들을 참조하는 foreign key들이 어떻게 처리될 것인지를 지정한다: <literal>ignore</literal>는 한 개의 누락된 행을
한 개의 null 연관으로 취급할 것이다.
</para>
</callout>
<callout arearefs="manytoone15">
<para>
<literal>entity-name</literal> (옵션): 연관된 클래스의 엔티티 이름.
</para>
</callout>
</calloutlist>
<callout arearefs="manytoone16">
<para>
<literal>formula</literal> (옵션): <emphasis>계산된</emphasis> foreign key에 대한 값을 정의하는 SQL 표현식.
</para>
</callout>
</programlistingco>
<para>
<literal>cascade</literal> 속성 값을 <literal>none</literal> 아닌 어떤 의미있는 다른 값으로 설정하는 것은
어떤 오퍼레이션들을 연관된 객체에게 보급할 것이다. 유의미한 값들은 Hibernate의 기본 오퍼레이션들의 이름들,
<literal>persist, merge, delete, save-update, evict, replicate, lock, refresh</literal>
뿐만 아니라 특별한 값들, 즉 <literal>delete-orphan</literal><literal>all</literal> 그리고 오퍼레이션 이름들의
쉼표 분리된 조합들, 예를 들면 <literal>cascade="persist,merge,evict"</literal> 또는
<literal>cascade="all,delete-orphan"</literal>이다. 전체 설명은
<xref linkend="objectstate-transitive"/>를 보라. 단일값 연관들(many-to-one 연관과
one-to-one 연관)은 orphan delete를 지원하지 않음을 노트하라.
</para>
<para>
일반적인 <literal>many-to-one</literal> 선언은 다음과 같이 간단하게 보여진다:
</para>
<programlisting><![CDATA[<many-to-one name="product" class="Product" column="PRODUCT_ID"/>]]></programlisting>
<para>
<literal>property-ref</literal> 속성은 오직 foreign key가 프라이머리 키가 아닌 연관된 테이블의 유일 키를 참조하는
리거시 데이터를 매핑하는데만 사용된다. 이것은 꼴사나운 관계형 모형이다. 예를 들어, <literal>Product</literal>
클래스가 프라이머리 키를 아닌, 유일한 시리얼 번호를 갖는다고 가정하자.(<literal>unique</literal> 속성은
SchemaExport 도구로 Hibernate의 DDL 생성을 제어한다.)
</para>
<programlisting><![CDATA[<property name="serialNumber" unique="true" type="string" column="SERIAL_NUMBER"/>]]></programlisting>
<para>
그런 다음 <literal>OrderItem</literal>에 대한 매핑은 다음을 사용할 것이다:
</para>
<programlisting><![CDATA[<many-to-one name="product" property-ref="serialNumber" column="PRODUCT_SERIAL_NUMBER"/>]]></programlisting>
<para>
하지만 이것은 확실히 권장되지 않는다.
</para>
<para>
만일 참조된 유일 키가 연관된 엔티티의 여러 프로퍼티들을 포함할 경우, 당신은 명명된 <literal>&lt;properties&gt;</literal>
요소 내부에 참조된 프로퍼티들을 매핑할 것이다.
</para>
<para>
만일 참조된 유일키가 컴포넌트의 프로퍼티일 경우, 당신은 하나의 프로퍼티 경로를 지정할 수 있다:
</para>
<programlisting><![CDATA[<many-to-one name="owner" property-ref="identity.ssn" column="OWNER_SSN"/>]]></programlisting>
</sect2>
<sect2 id="mapping-declaration-onetoone" revision="3">
<title>one-to-one</title>
<para>
또 다른 영속 클래스에 대한 one-to-one 연관관계는 <literal>one-to-one</literal> 요소를 사용하여 선언된다.
</para>
<programlistingco>
<areaspec>
<area id="onetoone1" coords="2 70"/>
<area id="onetoone2" coords="3 70"/>
<area id="onetoone3" coords="4 70"/>
<area id="onetoone4" coords="5 70"/>
<area id="onetoone5" coords="6 70"/>
<area id="onetoone6" coords="7 70"/>
<area id="onetoone7" coords="8 70"/>
<area id="onetoone8" coords="9 70"/>
<area id="onetoone9" coords="10 70"/>
<area id="onetoone10" coords="11 70"/>
</areaspec>
<programlisting><![CDATA[<one-to-one
name="propertyName"
class="ClassName"
cascade="cascade_style"
constrained="true|false"
fetch="join|select"
property-ref="propertyNameFromAssociatedClass"
access="field|property|ClassName"
formula="any SQL expression"
lazy="proxy|no-proxy|false"
entity-name="EntityName"
node="element-name|@attribute-name|element/@attribute|."
embed-xml="true|false"
foreign-key="foreign_key_name"
/>]]></programlisting>
<calloutlist>
<callout arearefs="onetoone1">
<para>
<literal>name</literal>: 프로퍼티의 이름.
</para>
</callout>
<callout arearefs="onetoone2">
<para>
<literal>class</literal> (옵션 - 디폴트는 reflection에 의해 결정된 프로퍼티 타입):
연관된 클래스의 이름.
</para>
</callout>
<callout arearefs="onetoone3">
<para>
<literal>cascade</literal> (옵션) 어느 오퍼레이션들이 부모 객체로부터 연관된 객체로
케스케이드 될 것인지를 지정한다.
</para>
</callout>
<callout arearefs="onetoone4">
<para>
<literal>constrained</literal> (옵션) 매핑된 테이블의 프라이머리 키에 대한 foreign 키
컨스트레인트가 연관된 클래스의 테이블을 참조하는지 여부를 지정한다. 이 옵션은 <literal>save()</literal>
<literal>delete()</literal>가 케스케이드 되는 순서에 영향을 주고, 그 연관이 프락시 될 것인지 여부를 결정한다
(또한 스키마 내보내기 도구에 의해 사용된다).
</para>
</callout>
<callout arearefs="onetoone5">
<para>
<literal>fetch</literal> (옵션 - 디폴트는 <literal>select</literal>):
outer-join 페칭 또는 순차적인 select 페칭 중에서 선택하라.
</para>
</callout>
<callout arearefs="onetoone6">
<para>
<literal>property-ref</literal>: (옵션) 이 클래스의 프라이머리 키에 연결된 연관 클래스의 프로퍼티의 이름.
만일 지정되지 않을 경우, 연관 클래스의 프라이머리 키가 사용된다.
</para>
</callout>
<callout arearefs="onetoone7">
<para>
<literal>access</literal> (옵션 - 디폴트는 <literal>property</literal>):
Hibernate가 프로퍼티 값에 접근 하는데 사용할 방도.
</para>
</callout>
<callout arearefs="onetoone8">
<para>
<literal>formula</literal> (옵션):
거의 모든 one to one 연관관계들은 소유하는 엔티티의 프라이머리 키로 매핑된다. 이것이 그 경우가 아닌 드문 경우들에서,
당신은 SQL formula 사용에 결합시킬 몇몇 다른 컬럼, 컬럼들, 또는 표현식을 지정할 수 있다.(예제는
<literal>org.hibernate.test.onetooneformula</literal>를 보라.)
</para>
</callout>
<callout arearefs="onetoone9">
<para>
<literal>lazy</literal> (옵션 - 디폴트는 <literal>proxy</literal>):
디폴트로 한쪽 끝 연관들이 프락시 된다. <literal>lazy="no-proxy"</literal>는 인스턴스 변수가 처음 접근될 때
그 프로퍼티가 lazily 페치될 것임을 지정한다(빌드-시 바이트코드 수단을 필요로 한다).
<literal>lazy="false"</literal>는 그 연관들이 항상 eagerly 페치될 것임을 지정한다. <emphasis>만일
<literal>constrained="false"</literal>인 경우에, 프락싱은 불가능하고 Hibernate는 그 연관을 eager 페치시킬 것이다!</emphasis>
</para>
</callout>
<callout arearefs="onetoone10">
<para>
<literal>entity-name</literal> (옵션): 연관된 클래스의 엔티티 이름.
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
one-to-one 연관관계에는 두 가지 변종이 존재한다:
</para>
<itemizedlist>
<listitem><para>
프라이머리 키 연관관계들
</para></listitem>
<listitem><para>
유일 foreign 키 연관관계들
</para></listitem>
</itemizedlist>
<para>
프라이머리 키 연관들은 특별한 테이블 컬럼을 필요로 하지 않는다; 만일 두 개의 행들이 그 연관에 의해 관계지워지면,
두 개의 테이블 행들은 동일한 프라이머리 키 값을 공유한다. 따라서 만일 두 개의 객체들이 프라이머리 키 연관에 의해
관계지워지도록 당신이 원할 경우, 당신은 그것들에 동일한 식별자 값이 할당되도록 해야 한다!
</para>
<para>
프라이머리 키 연관에 대해, 다음 매핑들을 <literal>Employee</literal><literal>Person</literal> 각각에 추가하라.
</para>
<programlisting><![CDATA[<one-to-one name="person" class="Person"/>]]></programlisting>
<programlisting><![CDATA[<one-to-one name="employee" class="Employee" constrained="true"/>]]></programlisting>
<para>
이제 우리는 PERSON 과 EMPLOYEE 테이블들에서 관계지워진 행들의 프라이머리 키들이 동일함을 확실히 해야 한다! 우리는
<literal>foreign</literal>로 명명되는 특별한 Hibernate 식별자 생성 방도를 사용한다:
</para>
<programlisting><![CDATA[<class name="person" table="PERSON">
<id name="id" column="PERSON_ID">
<generator class="foreign">
<param name="property">employee</param>
</generator>
</id>
...
<one-to-one name="employee"
class="Employee"
constrained="true"/>
</class>]]></programlisting>
<para>
그때 <literal>Person</literal>의 새로이 저장된 인스턴스는 그 <literal>Person</literal>
<literal>employee</literal> 프로퍼티에 대해 참조된 <literal>Employee</literal> 인스턴스와 동일한
프라이머리 키를 할당받는다.
</para>
<para>
달리, <literal>Employee</literal>로부터 <literal>Person</literal>으로의 유일 컨스트레인트를 가진
하나의 foreign key는 다음과 같이 표현될 수 있다:
</para>
<programlisting><![CDATA[<many-to-one name="person" class="Person" column="PERSON_ID" unique="true"/>]]></programlisting>
<para>
그리고 이 연관은 다음을 <literal>Person</literal> 매핑에 추가함으로써 양방향이 될 수 있다:
</para>
<programlisting><![CDATA[<one-to-one name"employee" class="Employee" property-ref="person"/>]]></programlisting>
</sect2>
<sect2 id="mapping-declaration-naturalid">
<title>natural-id</title>
<programlisting><![CDATA[<natural-id mutable="true|false"/>
<property ... />
<many-to-one ... />
......
</natural-id>]]></programlisting>
<para>
비록 우리가 프라이머리 키들로서 대용키들을 사용하는 것을 권장했을지라도, 당신은 여전히 모든 엔티티들에 대한 natural
키들을 식별하고자 원할 것이다. narutal 키는 유일(unique)하고 null이 아닌 프로퍼티 또는 프로퍼티들의 조합이다.
그것이 또한 불변하는 것일 경우가 더 좋다. <literal>&lt;natural-id&gt;</literal> 요소 내부에 있는 natural 키의
프로퍼티들을 매핑하라. Hibernate는 필수적인 유일 키와 null 허용가능한 컨스트레인트들을 생성시킬 것이고, 당신의
매핑은 보다 자가 설명적이게 될 것이다.
</para>
<para>
우리는 당신이 엔티티에 대한 narutal 키 프로퍼티들을 비교하는데 <literal>equals()</literal>
<literal>hashCode()</literal>를 구현할 것을 강력하게 권장한다.
</para>
<para>
이 매핑은 natural 프라이머리 키들을 가진 엔티티들을 위한 용도로 고안된 것은 아니다.
</para>
<itemizedlist spacing="compact">
<listitem>
<para>
<literal>mutable</literal> (옵션, 디폴트는 <literal>false</literal>):
디폴트로, narutal 식별자 프로퍼티들은 변경될 수 없는 것(상수)으로 가정된다.
</para>
</listitem>
</itemizedlist>
</sect2>
<sect2 id="mapping-declaration-component" revision="2">
<title>component, dynamic-component</title>
<para>
<literal>&lt;component&gt;</literal> 요소는 자식 객체의 프로퍼티들을 부모 클래스에 대한 테이블의 컬럼들로 매핑시킨다.
컴포넌트들은 그것들 자신의 프로퍼티들, 컴포넌트들, 또는 콜렉션들을 선언한다. 이래 "컴포넌트들"을 보라.
</para>
<programlistingco>
<areaspec>
<area id="component1" coords="2 45"/>
<area id="component2" coords="3 45"/>
<area id="component3" coords="4 45"/>
<area id="component4" coords="5 45"/>
<area id="component5" coords="6 45"/>
<area id="component6" coords="7 45"/>
<area id="component7" coords="8 45"/>
<area id="component8" coords="9 45"/>
</areaspec>
<programlisting><![CDATA[<component
name="propertyName"
class="className"
insert="true|false"
update="true|false"
access="field|property|ClassName"
lazy="true|false"
optimistic-lock="true|false"
unique="true|false"
node="element-name|."
>
<property ...../>
<many-to-one .... />
........
</component>]]></programlisting>
<calloutlist>
<callout arearefs="component1">
<para>
<literal>name</literal>: 프로퍼티의 이름.
</para>
</callout>
<callout arearefs="component2">
<para>
<literal>class</literal> (옵션 - 디폴트는 reflection에 의해 결정된 프로퍼티 타입):
컴포넌트(자식) 클래스의 이름.
</para>
</callout>
<callout arearefs="component3">
<para>
<literal>insert</literal>: 매핑된 컬럼들이 SQL <literal>INSERT</literal>들 속에
나타나야 하는가?
</para>
</callout>
<callout arearefs="component4">
<para>
<literal>update</literal>: 매핑된 컬럼들이 SQL <literal>UPDATE</literal>들 속에
나타나야 하는가?
</para>
</callout>
<callout arearefs="component5">
<para>
<literal>access</literal> (옵션 - 디폴트는 <literal>property</literal>):
Hibernate가 프로퍼티 값에 액세스하는데 사용할 방도.
</para>
</callout>
<callout arearefs="component6">
<para>
<literal>lazy</literal> (옵션 - 디폴트는 <literal>false</literal>):
인스턴스 변수가 처음으로 액세스될 때 이 컴포넌트가 lazily(느리게) 페치되어야 하는지 여부를 지정한다
(빌드 시 바이트코드 수단을 필요로 한다).
</para>
</callout>
<callout arearefs="component7">
<para>
<literal>optimistic-lock</literal> (옵션 - 디폴트는 <literal>true</literal>):
이 컴포넌트에 대한 업데이트들이 optimistic 잠금을 획득하는 것을 필요로 하는지 여부를 지정한다.
달리 말해 이 프로퍼티가 dirty 일 때 버전 증가가 발생할 것인지 여부를 결정한다.
</para>
</callout>
<callout arearefs="component8">
<para>
<literal>unique</literal> (옵션 - 디폴트는 <literal>false</literal>):
유일 컨스트레인트가 컴포넌트의 모든 매핑된 컬럼들에 대해 존재하는지 여부를 지정한다.
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
자식 <literal>&lt;property&gt;</literal> 태그들은 자식 클래스의 프로퍼티들을 테이블 컬럼들로 매핑시킨다.
</para>
<para>
<literal>&lt;component&gt;</literal> 요소는 컴포넌트 클래스의 프로퍼티를 포함하는 엔티티에 대한 참조로서 매핑시키는
<literal>&lt;parent&gt;</literal> 서브요소를 허용한다.
</para>
<para>
<literal>&lt;dynamic-component&gt;</literal> 요소는 컴포넌트로서 매핑될<literal>Map</literal>을 허용한다.
여기서 프로퍼티 이름들은 map의 키들을 참조한다. <xref linkend="components-dynamic"/>을 보라.
</para>
</sect2>
<sect2 id="mapping-declaration-properties" revision="2">
<title>properties</title>
<para>
<literal>&lt;properties&gt;</literal> 요소는 클래스의 프로퍼티들의 명명된, 논리적 그룹핑에 대한 정의를 허용한다.
그 구조에 대한 가장 중요한 사용은 그것이 프로퍼티들의 조합이 <literal>property-ref</literal>의 대상이 되는 것을
허용해준다는 점이다. 또한 그것은 다중 컬럼 유일 컨스트레인느를 정의하는 편리한 방법이다.
</para>
<programlistingco>
<areaspec>
<area id="properties1" coords="2 45"/>
<area id="properties2" coords="3 45"/>
<area id="properties3" coords="4 45"/>
<area id="properties4" coords="5 45"/>
<area id="properties5" coords="6 45"/>
</areaspec>
<programlisting><![CDATA[<properties
name="logicalName"
insert="true|false"
update="true|false"
optimistic-lock="true|false"
unique="true|false"
>
<property ...../>
<many-to-one .... />
........
</properties>]]></programlisting>
<calloutlist>
<callout arearefs="properties1">
<para>
<literal>name</literal>: 그룹핑의 논리적 이름 - 실제 프로퍼티 이름이 <emphasis>아니다</emphasis>.
</para>
</callout>
<callout arearefs="properties2">
<para>
<literal>insert</literal>: 매핑된 컬럼들이 SQL <literal>INSERT</literal>들 내에 나타날 것인가?
</para>
</callout>
<callout arearefs="properties3">
<para>
<literal>update</literal>: 매핑된 컬럼들이 SQL <literal>UPDATE</literal>들 내에 나타날 것인가?
</para>
</callout>
<callout arearefs="properties4">
<para>
<literal>optimistic-lock</literal> (옵션 - 디폴트는 <literal>true</literal>):
이들 프로퍼티들에 대한 업데이트들이 optimistic 잠금의 획득을 필요로 하는지 여부를 지정한다. 달리 말해
이 프로퍼티가 dirty 일 때 버전 증가가 발생할 것인지 여부를 결정한다.
</para>
</callout>
<callout arearefs="properties5">
<para>
<literal>unique</literal> (옵션 - 디폴트는 <literal>false</literal>):
유일 컨스트레인트가 컴포넌트의 모든 매핑된 컬럼들에 대해 존재하는지 여부를 지정한다.
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
예를 들어, 만일 우리가 다음 <literal>&lt;properties&gt;</literal> 매핑을 가질 경우:
</para>
<programlisting><![CDATA[<class name="Person">
<id name="personNumber"/>
...
<properties name="name"
unique="true" update="false">
<property name="firstName"/>
<property name="initial"/>
<property name="lastName"/>
</properties>
</class>]]></programlisting>
<para>
그 때 우리는 프라이머리 키가 아닌, <literal>Person</literal> 테이블의 이 유일 키를 참조하는 어떤 리거시 데이터 연관을
가질 수 있다:
</para>
<programlisting><![CDATA[<many-to-one name="person"
class="Person" property-ref="name">
<column name="firstName"/>
<column name="initial"/>
<column name="lastName"/>
</many-to-one>]]></programlisting>
<para>
우리는 리거시 데이터를 매핑시키는 컨텍스트 바깥에서 이런 종류의 것을 사용하는 것을 권장하지 않는다.
</para>
</sect2>
<sect2 id="mapping-declaration-subclass" revision="4">
<title>subclass</title>
<para>
마지막으로, 다형성 영속성은 루트 영속 클래스에 대한 각각의 서브클래스 선언을 필요로 한다.(권장되는)
table-per-class-hierarchy(테이블 당 클래스 계층구조) 매핑 방도의 경우, <literal>&lt;subclass&gt;</literal>
선언이 사용된다.
</para>
<programlistingco>
<areaspec>
<area id="subclass1" coords="2 55"/>
<area id="subclass2" coords="3 55"/>
<area id="subclass3" coords="4 55"/>
<area id="subclass4" coords="5 55"/>
</areaspec>
<programlisting><![CDATA[<subclass
name="ClassName"
discriminator-value="discriminator_value"
proxy="ProxyInterface"
lazy="true|false"
dynamic-update="true|false"
dynamic-insert="true|false"
entity-name="EntityName"
node="element-name"
extends="SuperclassName">
<property .... />
.....
</subclass>]]></programlisting>
<calloutlist>
<callout arearefs="subclass1">
<para>
<literal>name</literal>: 서브클래스의 전체 수식어가 붙은 클래스 이름.
</para>
</callout>
<callout arearefs="subclass2">
<para>
<literal>discriminator-value</literal> (옵션 - 디폴트는 클래스 이름):
개개의 서브클래스들을 구분짓는 값.
</para>
</callout>
<callout arearefs="subclass3">
<para>
<literal>proxy</literal> (옵션): lazy 초기화 프락시들을 사용하는데 클래스 또는 인터페이스를 지정한다.
</para>
</callout>
<callout arearefs="subclass4">
<para>
<literal>lazy</literal> (옵션 - 디폴트는 <literal>true</literal>):
<literal>lazy="false"</literal> 설정은 lazy 페칭의 사용을 불가능하게 만든다.
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
각각의 서브클래스는 그것 자신의 영속 프로퍼티들과 서브클래스들을 선언할 것이다. <literal>&lt;version&gt;</literal>
프로퍼티와 <literal>&lt;id&gt;</literal> 프로퍼티는 루트 클래스로부터 상속된다고 가정된다. 계층구조 내에서 각각의
서브클래스는 유일한 <literal>discriminator-value</literal>를 정의해야 한다. none이 지정될 경우, 전체 수식어가
붙은 자바 클래스 이름이 사용된다.
</para>
<para>
상속 매핑들에 대한 정보는 <xref linkend="inheritance"/>을 보라.
</para>
</sect2>
<sect2 id="mapping-declaration-joinedsubclass" revision="3">
<title>joined-subclass</title>
<para>
다른 방법으로 각각의 서브클래스는 그것 자신이 테이블로 매핑될 수 있다(table-per-subclass 매핑 방도). 상속된 상태는
슈퍼클래스의 테이블과 조인함으로써 검색된다. 우리는 <literal>&lt;joined-subclass&gt;</literal> 요소를 사용한다.
</para>
<programlistingco>
<areaspec>
<area id="joinedsubclass1" coords="2 45"/>
<area id="joinedsubclass2" coords="3 45"/>
<area id="joinedsubclass3" coords="4 45"/>
<area id="joinedsubclass4" coords="5 45"/>
</areaspec>
<programlisting><![CDATA[<joined-subclass
name="ClassName"
table="tablename"
proxy="ProxyInterface"
lazy="true|false"
dynamic-update="true|false"
dynamic-insert="true|false"
schema="schema"
catalog="catalog"
extends="SuperclassName"
persister="ClassName"
subselect="SQL expression"
entity-name="EntityName"
node="element-name">
<key .... >
<property .... />
.....
</joined-subclass>]]></programlisting>
<calloutlist>
<callout arearefs="joinedsubclass1">
<para>
<literal>name</literal>: 서브클래스의 전체 수식어가 붙은 클래스 명.
</para>
</callout>
<callout arearefs="joinedsubclass2">
<para>
<literal>table</literal>: 서브클래스 테이블의 이름.
</para>
</callout>
<callout arearefs="joinedsubclass3">
<para>
<literal>proxy</literal> (옵션): 프락시들을 lazy 초기화 시키는데 사용할 클래스 또는 인터페이스를 지정한다.
</para>
</callout>
<callout arearefs="joinedsubclass4">
<para>
<literal>lazy</literal> (옵션 - 디폴트는 <literal>true</literal>):
<literal>lazy="false"</literal> 설정은 lazy 페칭을 사용불가능하게 만든다
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
판별자(discriminator) 컬럼은 이 매핑 방도에 필요하지 않다. 하지만 각각의 서브클래스는 <literal>&lt;key&gt;</literal> 요소를
사용하여 객체 식별자를 보관하는 테이블 컬럼을 선언해야 한다. 이 장의 시작 부분에 있는 매핑은 다음과 같이 다시 작성될 것이다:
</para>
<programlisting><![CDATA[<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="eg">
<class name="Cat" table="CATS">
<id name="id" column="uid" type="long">
<generator class="hilo"/>
</id>
<property name="birthdate" type="date"/>
<property name="color" not-null="true"/>
<property name="sex" not-null="true"/>
<property name="weight"/>
<many-to-one name="mate"/>
<set name="kittens">
<key column="MOTHER"/>
<one-to-many class="Cat"/>
</set>
<joined-subclass name="DomesticCat" table="DOMESTIC_CATS">
<key column="CAT"/>
<property name="name" type="string"/>
</joined-subclass>
</class>
<class name="eg.Dog">
<!-- mapping for Dog could go here -->
</class>
</hibernate-mapping>]]></programlisting>
<para>
상속 매핑들에 대한 정보는 <xref linkend="inheritance"/>을 보라.
</para>
</sect2>
<sect2 id="mapping-declaration-unionsubclass" revision="2">
<title>union-subclass</title>
<para>
제3의 옵션은 상속 계층구조의 concrete 클래스들 만을 테이블들로 매핑하는 것이다 (table-per-concrete-class 방도). 여기서
각각의 테이블은 상속된 상태를 포함하여 클래스의 모든 영속 상태를 정의한다. Hibernate에서, 그것은 그런 상속 계층구조들을
명시적으로 매핑하는데 필수적이지 않다. 당신은 별도의 <literal>&lt;class&gt;</literal> 선언을 가진 각각의 클래스를
간단히 매핑시킬 수 있다. 하지만 당신이 다형성 연관관계들(예를 들면 당신의 계층구조의 슈퍼클래스에 대한 연관)을 사용하고자 원할
경우, 당신은 <literal>&lt;union-subclass&gt;</literal> 매핑을 사용할 필요가 있다.
</para>
<programlistingco>
<areaspec>
<area id="unionsubclass1" coords="2 45"/>
<area id="unionsubclass2" coords="3 45"/>
<area id="unionsubclass3" coords="4 45"/>
<area id="unionsubclass4" coords="5 45"/>
</areaspec>
<programlisting><![CDATA[<union-subclass
name="ClassName"
table="tablename"
proxy="ProxyInterface"
lazy="true|false"
dynamic-update="true|false"
dynamic-insert="true|false"
schema="schema"
catalog="catalog"
extends="SuperclassName"
abstract="true|false"
persister="ClassName"
subselect="SQL expression"
entity-name="EntityName"
node="element-name">
<property .... />
.....
</union-subclass>]]></programlisting>
<calloutlist>
<callout arearefs="unionsubclass1">
<para>
<literal>name</literal>: 서브클래스의 전체 수식어가 붙은 클래스 명.
</para>
</callout>
<callout arearefs="unionsubclass2">
<para>
<literal>table</literal>: 서브클래스 테이블의 이름.
</para>
</callout>
<callout arearefs="unionsubclass3">
<para>
<literal>proxy</literal> (옵션): 프락시들을 lazy 초기화 시키는데 사용할 클래스 또는 인터페이스를 지정한다.
</para>
</callout>
<callout arearefs="unionsubclass4">
<para>
<literal>lazy</literal> (옵션 - 디폴트는 <literal>true</literal>):
<literal>lazy="false"</literal> 설정은 lazy 페칭을 사용불가능하게 만든다.
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
이 매핑 방도에는 판별자 컬럼이나 키 컬럼이 필요하지 않다.
</para>
<para>
상속 매핑들에 대한 정보는 <xref linkend="inheritance"/>을 보라.
</para>
</sect2>
<sect2 id="mapping-declaration-join" revision="3">
<title>join</title>
<para>
<literal>&lt;join&gt;</literal> 요소를 사용하면, 한 개의 클래스의 프로퍼티들을 몇 개의 테이블들로 매핑시키는 것이
가능하다.
</para>
<programlistingco>
<areaspec>
<area id="join1" coords="2 50"/>
<area id="join2" coords="3 50"/>
<area id="join3" coords="4 50"/>
<area id="join4" coords="5 50"/>
<area id="join5" coords="6 50"/>
<area id="join6" coords="7 50"/>
</areaspec>
<programlisting><![CDATA[<join
table="tablename"
schema="owner"
catalog="catalog"
fetch="join|select"
inverse="true|false"
optional="true|false">
<key ... />
<property ... />
...
</join>]]></programlisting>
<calloutlist>
<callout arearefs="join1">
<para>
<literal>table</literal>: 조인된 테이블의 이름.
</para>
</callout>
<callout arearefs="join2">
<para>
<literal>schema</literal> (옵션): 루트 <literal>&lt;hibernate-mapping&gt;</literal> 요소에
의해 지정된 스키마 이름을 오버라이드 시킨다
</para>
</callout>
<callout arearefs="join3">
<para>
<literal>catalog</literal> (옵션): 루트 <literal>&lt;hibernate-mapping&gt;</literal> 요소에
의해 지정된 카타록 이름을 오버라이드 시킨다.
</para>
</callout>
<callout arearefs="join4">
<para>
<literal>fetch</literal> (옵션 - 디폴트는 <literal>join</literal>):
<literal>join</literal>으로 설정될 경우, 디폴트로 Hibernate는 하나의 클래스 또는 그것의 슈퍼 클래스들에 의해
정의된 <literal>&lt;join&gt;</literal>을 검색하는데 inner join을 사용하고 서브클래스에 의해 정의된
<literal>&lt;join&gt;</literal>을 검색하는데 outer join을 사용할 것이다. 만일 <literal>select</literal>
설정할 경우, Hibernate는 서브클래스 상에 정의된 <literal>&lt;join&gt;</literal>에 대해 sequential
select를 사용할 것이고, 그것은 한 행이 서브클래스의 인스턴스를 표현하는 것으로 판명되는 경우에만 명령이 내려질 것이다.
inner join들은 여전히 클래스와 그것의 슈퍼클래스들에 의해 정의된 <literal>&lt;join&gt;</literal>을 검색하는데
사용될 것이다.
</para>
</callout>
<callout arearefs="join5">
<para>
<literal>inverse</literal> (옵션 - 디폴트는 <literal>false</literal>):
이용 가능할 경우, Hibernate는 이 조인에 의해 정의된 프로퍼티들을 삽입시키거나 업데이트하려고 시도하지
않을 것이다.
</para>
</callout>
<callout arearefs="join6">
<para>
<literal>optional</literal> (옵션 - 디폴트는 <literal>false</literal>):
이용 가능할 경우, Hibernate는 이 조인에 의해 정의된 프로퍼티들이 null이 아닐 경우에만 한 행을 삽입시킬 것이고
그 프로퍼티들을 검색하는데 outer join을 항상 사용할 것이다.
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
예를 들어, (모든 프로퍼티들에 대해 value 타입 의미를 유지하면서) 개인의 주소 정보는 별도의 테이블에 매핑될 수 있다:
</para>
<programlisting><![CDATA[<class name="Person"
table="PERSON">
<id name="id" column="PERSON_ID">...</id>
<join table="ADDRESS">
<key column="ADDRESS_ID"/>
<property name="address"/>
<property name="zip"/>
<property name="country"/>
</join>
...]]></programlisting>
<para>
이 특징은 자주 리거시 데이터 모형들에 대해서만 유용하고, 우리는 클래스들과 잘 정제된 도메인 모형 보다 더 적은 테이블들을
권장한다. 하지만 뒷 부분에 설명되어 있듯이, 그것은 하나의 계층구조 내에 있는 상속 매핑 방도들 사이를 전환하는 것에 유용하다.
</para>
</sect2>
<sect2 id="mapping-declaration-key">
<title>key</title>
<para>
우리는 지금까지 몇 번 나타났던 <literal>&lt;key&gt;</literal> 요소를 보았다. 그것은 부모 매핑 요소가 새로운 테이블에
대한 조인을 정의하는 어느 곳에서나 나타나고, 그것은 조인된 테이블의 foreign 키를 정의하고, 그것은 원래의 테이블의
프라이머리 키를 참조한다.
</para>
<programlistingco>
<areaspec>
<area id="key1" coords="2 50"/>
<area id="key2" coords="3 50"/>
<area id="key3" coords="4 50"/>
<area id="key4" coords="5 50"/>
<area id="key5" coords="6 50"/>
<area id="key6" coords="7 50"/>
</areaspec>
<programlisting><![CDATA[<key
column="columnname"
on-delete="noaction|cascade"
property-ref="propertyName"
not-null="true|false"
update="true|false"
unique="true|false"
/>]]></programlisting>
<calloutlist>
<callout arearefs="key1">
<para>
<literal>column</literal> (옵션):
foreign key 컬럼의 이름. 이것은 또한 내포된 <literal>&lt;column&gt;</literal> 요소(들)에 의해 지정될 수 있다.
</para>
</callout>
<callout arearefs="key2">
<para>
<literal>on-delete</literal> (옵션 - 디폴트는 <literal>noaction</literal>):
foreign key 컨스트레인트가 데이터베이스 레벨의 cascade delete를 사용가능하도록 할 것인지 여부를 지정한다.
</para>
</callout>
<callout arearefs="key3">
<para>
<literal>property-ref</literal> (옵션):
foreign key가 원래의 테이블의 프라이머리 키가 아닌 컬럼들을 참조함을 지정한다. (리거시 데이터에 제공됨.)
</para>
</callout>
<callout arearefs="key4">
<para>
<literal>not-null</literal> (옵션):
foreign 키 컬럼들이 not null 임를 지정한다(이것은 foreign 키가 또한 프라이머리 키의 부분일 때마다 함축된다).
</para>
</callout>
<callout arearefs="key5">
<para>
<literal>update</literal> (옵션):
foreign 키가 결코 업데이트되지 않아야 함을 지정한다(이것은 foreign 키가 또한 프라이머리 키의 부분일 때마다
함축된다).
</para>
</callout>
<callout arearefs="key6">
<para>
<literal>unique</literal> (옵션):
foreign 키가 유일 컨스트레인트를 가져야 함을 지정한다 (이것은 foreign 키가 또한 프라이머리 키의 부분일
때마다 함축된다).
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
우리는 delete 퍼포먼스가 중요한 시스템들에 대해 권장하고, 모든 키들은 <literal>on-delete="cascade"</literal>
정의되고, Hibernate는 많은 <literal>DELETE</literal> 문장들 대신에, 데이터베이스 레벨의
<literal>ON CASCADE DELETE</literal> 컨스트레인트를 사용할 것이다. 이 특징은 Hibernate의 통상적인 버전화된
데이터에 대한 optimistic 잠금 방도를 무시한다는 점을 알고 있어라.
</para>
<para>
<literal>not-null</literal> 속성과 <literal>update</literal> 속성들은 단방향 one to many 연관관계를 매핑할 때
유용하다. 만일 당신이 단방향 one to many를 null이 허용되지 않는 foreign 키로 매핑할 경우, 당신은
<literal>&lt;key not-null="true"&gt;</literal>를 사용하여 그 키 컬럼을 선언<emphasis>해야 한다</emphasis>.
</para>
</sect2>
<sect2 id="mapping-column" revision="4">
<title>column 요소와 formula 요소</title>
<para>
column 속성을 허용하는 임의의 매핑 요소는 대안적으로 하나의 <literal>&lt;column&gt;</literal> 서브요소를 수용할 것이다.
비슷하게 <literal>&lt;formula&gt;</literal><literal>formula</literal> 속성에 대한 대안이다.
</para>
<programlisting><![CDATA[<column
name="column_name"
length="N"
precision="N"
scale="N"
not-null="true|false"
unique="true|false"
unique-key="multicolumn_unique_key_name"
index="index_name"
sql-type="sql_type_name"
check="SQL expression"
default="SQL expression"/>]]></programlisting>
<programlisting><![CDATA[<formula>SQL expression</formula>]]></programlisting>
<para>
<literal>column</literal> 속성과 <literal>formula</literal> 속성은 예를 들어 신종 조인 조건들을 표현하기 위해
동일한 property 또는 연관관계 매핑 내에 결합될 수 있다.
</para>
<programlisting><![CDATA[<many-to-one name="homeAddress" class="Address"
insert="false" update="false">
<column name="person_id" not-null="true" length="10"/>
<formula>'MAILING'</formula>
</many-to-one>]]></programlisting>
</sect2>
<sect2 id="mapping-declaration-import">
<title>import</title>
<para>
당신의 어플리케이션이 동일한 이름을 가진 두 개의 영속 클래스들을 갖고, 당신이 Hibernate 질의들 내에서 전체 수식어가 붙은
(패키지)이름을 지정하는 것을 원하지 않는다고 가정하자. 클래스들은 <literal>auto-import="true"</literal>에 의존하기
보다 명시적으로 "임포트 될 " 것이다. 당신은 심지어 명시적으로 매핑되지 않는 클래스들과 인터페이스들을 임포트 시킬 수(가져오기 할 수)
있다.
</para>
<programlisting><![CDATA[<import class="java.lang.Object" rename="Universe"/>]]></programlisting>
<programlistingco>
<areaspec>
<area id="import1" coords="2 40"/>
<area id="import2" coords="3 40"/>
</areaspec>
<programlisting><![CDATA[<import
class="ClassName"
rename="ShortName"
/>]]></programlisting>
<calloutlist>
<callout arearefs="import1">
<para>
<literal>class</literal>: 임의의 Java 클래스의 전체 수식어가 붙은 클래스 이름.
</para>
</callout>
<callout arearefs="import2">
<para>
<literal>rename</literal> (옵션 - 디폴트는 수식어가 붙지 않은 클래스 이름):
질의 언어 내에서 사용될 이름.
</para>
</callout>
</calloutlist>
</programlistingco>
</sect2>
<sect2 id="mapping-types-anymapping" revision="2">
<title>any</title>
<para>
하나 이상의 프로퍼티 매핑 타입이 존재한다. <literal>&lt;any&gt;</literal> 매핑 요소는 여러 테이블들로부터 클래스들에
대한 하나의 다형성 연관관계를 정의한다. 이 매핑 타입은 언제나 하나 이상의 컬럼을 필요로 한다. 첫 번째 컬럼은 연관된 엔티티의
타입을 보관한다. 나머지 컬럼들은 식별자를 보관한다. 이런 종류의 연관관계들에 대해 foreign key 컨스트레인트를 지정하는 것이
불가능해서, 이것은 (다형성) 연관관계들을 매핑하는 통상적인 방법으로서 가장 확실한 수단이 아니다. 당신은 매우 특별한 경우들
(예를 들어 감사 로그들, 사용자 세션 데이터 등)에서만 이것을 사용해야 한다.
</para>
<para>
<literal>meta-type</literal> 속성은 어플리케이션으로 하여금 데이터베이스 컬럼 값들을 <literal>id-type</literal>
의해 지정된 타입의 식별자 프로퍼티들을 가진 영속 클래스들로 매핑시키는 맞춤형 타입을 지정하도록 한다. 당신은 meta-type의
값들로부터 클래스 이름들로의 매핑을 지정해야 한다.
</para>
<programlisting><![CDATA[<any name="being" id-type="long" meta-type="string">
<meta-value value="TBL_ANIMAL" class="Animal"/>
<meta-value value="TBL_HUMAN" class="Human"/>
<meta-value value="TBL_ALIEN" class="Alien"/>
<column name="table_name"/>
<column name="id"/>
</any>]]></programlisting>
<programlistingco>
<areaspec>
<area id="any1" coords="2 50"/>
<area id="any2" coords="3 50"/>
<area id="any3" coords="4 50"/>
<area id="any4" coords="5 50"/>
<area id="any5" coords="6 50"/>
<area id="any6" coords="7 50"/>
</areaspec>
<programlisting><![CDATA[<any
name="propertyName"
id-type="idtypename"
meta-type="metatypename"
cascade="cascade_style"
access="field|property|ClassName"
optimistic-lock="true|false"
>
<meta-value ... />
<meta-value ... />
.....
<column .... />
<column .... />
.....
</any>]]></programlisting>
<calloutlist>
<callout arearefs="any1">
<para>
<literal>name</literal>: 프로퍼티 이름.
</para>
</callout>
<callout arearefs="any2">
<para>
<literal>id-type</literal>: 식별자 타입.
</para>
</callout>
<callout arearefs="any3">
<para>
<literal>meta-type</literal> (옵션 - 디폴트는 <literal>string</literal>):
discriminator 매핑에 허용되는 임의의 타입.
</para>
</callout>
<callout arearefs="any4">
<para>
<literal>cascade</literal> (optional- defaults to <literal>none</literal>):
cascade 스타일.
</para>
</callout>
<callout arearefs="any5">
<para>
<literal>access</literal> (옵션 - 디폴트는 <literal>property</literal>):
Hibernate가 프로퍼티 값에 접근하는데 사용할 방도.
</para>
</callout>
<callout arearefs="any6">
<para>
<literal>optimistic-lock</literal> (옵션 - 디폴트는 <literal>true</literal>):
이 프로퍼티에 대한 업데이트들이 optimistic 잠금 획득을 필요로 하는지 여부를 지정한다. 달리 말해,
이 프로퍼티가 dirty일 경우에 버전증가가 발생할 것인지 여부를 정의한다.
</para>
</callout>
</calloutlist>
</programlistingco>
</sect2>
</sect1>
<sect1 id="mapping-types">
<title>Hibernate 타입들</title>
<sect2 id="mapping-types-entitiesvalues" revision="1">
<title>엔티티들과 값들</title>
<para>
영속 서비스에 관한 여러 Java 언어-레벨의 객체들을 이해하기 위해, 우리는 그것들을 다음 두 개의 그룹들로 분류할 필요가 있다:
</para>
<para>
<emphasis>entity</emphasis>는 엔티티에 대한 참조들을 보관하는 임의의 다른 객체들과는 독립적으로 존재한다. 참조되지 않은
객체가 쓰레기 수집되는 통상의 자바 모형과 이것은 대조적이다. (저장들과 삭제들이 부모 엔티티로부터 그것의 자식으로의 케스케이드
되는 경우를 제외하면) 엔티티들은 명시적으로 저장되고 삭제되어야 한다. 이것은 도달 가능성(reachablity)에 의한 객체 영속성의
ODMG 모형과는 다르다 - 그리고 어플리케이션 객체들이 대형 시스템들에서 대개 어떻게 사용되는가에 훨씬 더 가깝게 대응한다.
엔티티들은 순환 참조와 공유 참조들을 지원한다. 그것들 또한 버전화 될 수 있다.
</para>
<para>
엔티티의 영속 상태는 다른 엔티티들에 대한 참조들과 <emphasis>value</emphasis> 타입들로 구성된다. 값들은 원시 타입들,
콜렉션들(하나의 콜렉션 내부에 있지 않는 것들), 컴포넌트들, 그리고 어떤 불변의 객체들이다. entities와는 달리, (특별한
콜렉션들과 컴포넌트들에서) 값들은 도달가능성(reachability)에 의해 영속화 <emphasis>되고</emphasis> 삭제 된다.
value 객체들(과 원시 타입들)이 그것들의 포함하는 엔티티에 따라 영속화 되고 삭제 되므로, 그것들은 독립적으로 버전화 되지
않는다. 값들은 독립적인 엔티티를 갖지 않아서, 그것들은 두 개의 엔티티들이나 콜렉션들에 의해 공유될 수 없다.
</para>
<para>
지금까지 우리는 엔티티들을 참조하기 위해 "영속 클래스"를 사용해 왔다. 우리는 그것을 계속 사용할 것이다. 하지만 엄격히 말해,
영속 상태를 가진 모든 사용자 정의 클래스들은 엔티티들이 아니다. <emphasis>컴포넌트</emphasis>는 value 의미를 가진
사용자 정의 클래스이다. <literal>java.lang.String</literal> 타입의 자바 프로퍼티는 또한 value 의미를 갖는다.
이 정의가 주어지면, 우리는 JDK에 의해 제공된 모든 타입들(클래스들)이 자바에서 value 타입 의미를 갖고, 반면에 사용자 정의
타입들은 엔티티 또는 type 의미로서 매핑된다고 말할 수 있다. 이 판단은 어플리케이션 개발자에게 달려 있다. 도메인 모형에서
엔티티 클래스에 대한 좋은 힌트는 그 클래스의 하나의 인스턴스에 대한 공유된 참조들인 반면에, composition이나 aggregation은
대개 value 타입으로 변환된다.
</para>
<para>
우리는 문서를 통해 두 개념들을 다시 고찰할 것이다.
</para>
<para>
도점점은 Java type 시스템(과 엔티티들 및 value 타입들에 대한 개발자의 정의)를 SQL/데이터베이스 type 타입으로 매핑하는
것이다. 두 시스템들 사이의 다리는 Hibernate에 의해 제공된다: 엔티티들의 경우 우리는 <literal>&lt;class&gt;</literal>,
<literal>&lt;subclass&gt;</literal> 등을 사용한다.value 타입들의 경우 우리는 대개<literal>type</literal> 속성을 가진
<literal>&lt;property&gt;</literal>, <literal>&lt;component&gt;</literal> 등을 사용한다. 이 속성의 값은
Hibernate <emphasis>매핑 타입</emphasis>의 이름이다. Hibernate는 (표준 JDK value 타입들에 대해) 많은 매핑들을
제공한다. 나중에 보게 되듯이, 당신은 당신 자신의 매핑 타입들을 작성할 수 있고 마찬가지로 당신의 맞춤형 변환 방도들을 구현할 수
있다.
</para>
<para>
콜렉션들을 제외한 모든 미리 빌드된 Hibernate 타입들은 null 의미를 지원한다.
</para>
</sect2>
<sect2 id="mapping-types-basictypes" revision="3">
<title>기본 value 타입들</title>
<para>
미리-만들어진 <emphasis>기본 매핑 타입들</emphasis>은 대략 다음과 같이 카테고리로 분류된다
<variablelist>
<varlistentry>
<term><literal>integer, long, short, float, double, character, byte,
boolean, yes_no, true_false</literal></term>
<listitem>
<para>
자바 원시타입들이나 wrapper 클래스들로부터 적절한(벤더-지정적인) SQL 컬럼 타입들로의 타입 매핑.
<literal>boolean, yes_no</literal><literal>true_false</literal>
Java <literal>boolean</literal>이나 <literal>java.lang.Boolean</literal>에 대한
모든 대체적인 인코딩들이다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>string</literal></term>
<listitem>
<para>
<literal>java.lang.String</literal>으로부터 <literal>VARCHAR</literal>
(또는 Oracle <literal>VARCHAR2</literal>)로의 타입 매핑.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>date, time, timestamp</literal></term>
<listitem>
<para>
<literal>java.util.Date</literal>와 그것의 서브클래스로부터 SQL 타입들인
<literal>DATE</literal>, <literal>TIME</literal>, <literal>TIMESTAMP</literal>
(또는 등가물)로의 타입 매핑들.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>calendar, calendar_date</literal></term>
<listitem>
<para>
<literal>java.util.Calendar</literal>로부터 SQL 타입들인
<literal>TIMESTAMP</literal>, <literal>DATE</literal> (또는 등가물)로의 타입 매핑들.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>big_decimal, big_integer</literal></term>
<listitem>
<para>
<literal>java.math.BigDecimal</literal><literal>java.math.BigInteger</literal>로부터
<literal>NUMERIC</literal> (또는 Oracle <literal>NUMBER</literal>)로의 타입 매핑들.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>locale, timezone, currency</literal></term>
<listitem>
<para>
<literal>java.util.Locale</literal>, <literal>java.util.TimeZone</literal>, 그리고
<literal>java.util.Currency</literal>로부터 <literal>VARCHAR</literal>(또는 Oracle
<literal>VARCHAR2</literal>)로의 타입 매핑. <literal>Locale</literal><literal>Currency</literal>
인스턴스들은 그것들의 ISO 코드들로 매핑된다. <literal>TimeZone</literal>의 인스턴스들은 그것들의
<literal>ID</literal>로 매핑된다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>class</literal></term>
<listitem>
<para>
<literal>java.lang.Class</literal>로부터 <literal>VARCHAR</literal> (또는 Oracle
<literal>VARCHAR2</literal>)로의 타입 매핑. <literal>Class</literal>는 그것의 전체
수식어가 붙은 이름으로 매핑된다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>binary</literal></term>
<listitem>
<para>
byte 배열들을 적절한 SQL binary 타입으로 매핑시킨다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>text</literal></term>
<listitem>
<para>
long Java 문자열을 SQL <literal>CLOB</literal> 또는 <literal>TEXT</literal> 타입으로
매핑시킨다
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>serializable</literal></term>
<listitem>
<para>
serializable Java 타입들을 적절한 SQL binary 타입으로 매핑시킨다. 당신은 또한 디폴트로 기본 타입이
아닌 serializable 자바 클래스 또는 인터페이스의 이름을 가진 Hibernate 타입 <literal>serializable</literal>
나타낼 수도 있다.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>clob, blob</literal></term>
<listitem>
<para>
<literal>java.sql.Clob</literal><literal>java.sql.Blob</literal> JDBC 클래스들에 대한 타입 매핑들.
이들 타입들은 몇몇 어플리케이션들에서는 불편하다. 왜냐하면 blob 또는 clob 객체는 트랜잭션 외부에서 재사용될 수 없기
때문이다.(게다가 드라이버 지원이 비일관적이고 페치되어야 한다)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>imm_date, imm_time, imm_timestamp, imm_calendar, imm_calendar_date,
imm_serializable, imm_binary</literal>
</term>
<listitem>
<para>
대개 가변적인 Java 타입들로 간주되는 것에 대한 타입 매핑들. 여기서 Hibernate는 불변적인 Java 타입들에 대해서만 적절한
어떤 최적화를 행하고, 어플리케이션 그 객체를 변할 수 없는 것으로 취급한다. 예를 들어, 당신은 <literal>imm_timestamp</literal>로서
매핑된 인스턴스에 대해 <literal>Date.setTime()</literal>을 호출하지 않을 것이다. 프로퍼티의 값을 변경시키고,
그 변경을 영속화 시키기 위해서, 어플리케이션은 하나의 새로운 (동일하지 않은) 객체를 그 프로퍼티에 할당해야 한다.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
엔트리들과 콜렉션들의 유일 식별자들은 <literal>binary</literal>, <literal>blob</literal> 그리고 <literal>clob</literal>
제외한 기본 타입 중 어느 것일 수 있다. (Composite 식별자들이 또한 허용된다. 아래를 보라.)
</para>
<para>
기본 value 타입들은 <literal>org.hibernate.Hibernate</literal>에 정의되어 있는 대응하는
<literal>Type</literal> 상수들을 갖는다. 예를 들어, <literal>Hibernate.STRING</literal>
<literal>string</literal> 타입을 표현한다.
</para>
</sect2>
<sect2 id="mapping-types-custom" revision="2">
<title>맞춤형 value 타입들</title>
<para>
개발자들이 그들 자신들의 value 타입들을 생성시키는 것이 상대적으로 쉽다. 예를 들어, 당신은
<literal>java.lang.BigInteger</literal> 타입의 프로퍼티들을 <literal>VARCHAR</literal> 컬럼들로
영속화 시키고자 원할 수 있다. Hibernate는 이것을 위한 미리 만들어진 타입을 제공하지 않는다. 그러나 맞춤형 타입들은
프로퍼티(또는 콜렉션 요소)를 하나의 테이블 컬럼으로의 매핑하는 것에 제약되지 않는다. 따라서 예를 들어, 당신은
<literal>FIRST_NAME</literal>, <literal>INITIAL</literal>, <literal>SURNAME</literal> 컬럼들로
영속화 되는 <literal>java.lang.String</literal> 타입의 자바 프로퍼티<literal>getName()</literal>/
<literal>setName()</literal>를 가질 수 있다.
</para>
<para>
맞춤형 타입을 구현하려면, <literal>org.hibernate.UserType</literal> 또는 <literal>org.hibernate.CompositeUserType</literal>
구현하고 그 타입의 전체 수식어가 붙은 클래스명을 사용하여 프로퍼티들을 선언하라. 가능한 종류의 것들을 보려면
<literal>org.hibernate.test.DoubleStringType</literal>을 체크하라.
</para>
<programlisting><![CDATA[<property name="twoStrings" type="org.hibernate.test.DoubleStringType">
<column name="first_string"/>
<column name="second_string"/>
</property>]]></programlisting>
<para>
하나의 프로퍼티를 여러 개의 컬럼들로 매핑시키는 <literal>&lt;column&gt;</literal> 태그의 사용을 주목하라.
</para>
<para>
<literal>CompositeUserType</literal>, <literal>EnhancedUserType</literal>,
<literal>UserCollectionType</literal>, 그리고 <literal>UserVersionType</literal> 인터페이스들은
더 많은 특화된 사용들을 위한 지원을 제공한다.
</para>
<para>
당신은 매핑 파일 속에 <literal>UserType</literal>에 대한 파라미터들을 제공할 수도 있다. 이것을 행하기 위해,
당신의 <literal>UserType</literal><literal>org.hibernate.usertype.ParameterizedType</literal>
인터페이스를 구현해야 한다. 당신의 맞춤형 타입에 파라미터들을 제공하기 위해, 당신은 당신의 매핑 파일들 속에
<literal>&lt;type&gt;</literal> 요소를 사용할 수 있다.
</para>
<programlisting><![CDATA[<property name="priority">
<type name="com.mycompany.usertypes.DefaultValueIntegerType">
<param name="default">0</param>
</type>
</property>]]></programlisting>
<para>
<literal>UserType</literal>은 이제 그것에 전달된 <literal>Properties</literal> 객체로부터
<literal>default</literal>로 명명된 파라미터에 대한 값을 검색할 수 있다.
</para>
<para>
만일 당신이 매우 자주 어떤 UserType을 사용할 경우, 그것은 그것에 대한 더 짧은 이름을 정의하는 것이 유용할 수 있다.
<literal>&lt;typedef&gt;</literal> 요소를 사용하여 이것을 행할 수 있다. Typedef들은 이름을 맞춤형 타입에
할당하고, 또한 만일 그 타입이 파라미터화 된 경우에 디폴트 파라미터 값들의 리스트를 포함할 수도 있다.
</para>
<programlisting><![CDATA[<typedef class="com.mycompany.usertypes.DefaultValueIntegerType" name="default_zero">
<param name="default">0</param>
</typedef>]]></programlisting>
<programlisting><![CDATA[<property name="priority" type="default_zero"/>]]></programlisting>
<para>
property 매핑 상에 type 파라미터들을 사용함으로써 경우에 맞게 typedef 내에 제공된 파라미터들을 오버라이드 시키는 것이
가능하다.
</para>
<para>
비록 Hibernate의 풍부한 범위의 미리 만들어진 타입들과 컴포넌트들에 대한 지원이 당신이 가끔 맞춤형 타입을 사용할 <emphasis>필요가</emphasis>
거의 없을 것임을 의미할 지라도, 그럼에도 불구하고 그것은 당신의 어플리케이션에서 자주 발생하는 (엔티티가 아닌) 클래스들에 대해
맞춤형 타입들을 사용하는 좋은 형식으로 간주된다. 예를 들어 <literal>MonetaryAmount</literal> 클래스는 비록 그것이
컴포넌트로서 쉽게 매핑될 수 있을지라도, <literal>CompositeUserType</literal>에 대한 좋은 후보이다. 이것에 대한
하나의 동기는 추상화이다. 맞춤형 타입으로, 당신의 매핑 문서들은 화폐 값들을 표현하는 당신의 방법에서 가능한 변경들에 대해 장차
검증될 것이다.
</para>
</sect2>
</sect1>
<sect1 id="mapping-entityname">
<title>하나의 클래스를 한 번 이상 매핑하기</title>
<para>
하나의 특정한 영속 클래스에 대해 하나 이상의 매핑을 제공하는 것이 가능하다. 이 경우에 당신은 두 개의 매핑된 엔티티들의
인스턴스들 사이를 명확하게 하기 위해 <emphasis>하나의 엔티티 이름</emphasis>을 지정해야 한다. (디폴트로, 엔티티
이름은 클래스 이름과 동일한 것이다.) Hibernate는 영속 객체들에 대해 작업할 때, 질의들을 작성할 때, 또는 명명된 엔티티에
대한 연관들을 매핑할 때 당신으로 하여금 엔티티 이름을 지정하도록 한다.
</para>
<programlisting><![CDATA[<class name="Contract" table="Contracts"
entity-name="CurrentContract">
...
<set name="history" inverse="true"
order-by="effectiveEndDate desc">
<key column="currentContractId"/>
<one-to-many entity-name="HistoricalContract"/>
</set>
</class>
<class name="Contract" table="ContractHistory"
entity-name="HistoricalContract">
...
<many-to-one name="currentContract"
column="currentContractId"
entity-name="CurrentContract"/>
</class>]]></programlisting>
<para>
연관들은 이제 <literal>class</literal> 대신에 <literal>entity-name</literal>을 사용하여 어떻게 지정되는지를
주목하라.
</para>
</sect1>
<sect1 id="mapping-quotedidentifiers">
<title>SQL 인용부호 표시된 식별자들</title>
<para>
당신은 매핑 문서 내에서 테이블 또는 컬럼 이름을 역인용기호(`)들 속에 넣어서 생성된 SQL에서 식별자를 인용부호 처리하도록
Hibernate에게 강제할 수도 있다. Hibernate는 SQL <literal>Dialect</literal>에 대해 정확한 인용 스타일을 사용할
것이다(대개 이중 인용부호 이지만, SQL Server의 경우에는 모난 괄호들이고 MySQL의 경우에는 역인용부호(`)).
</para>
<programlisting><![CDATA[<class name="LineItem" table="`Line Item`">
<id name="id" column="`Item Id`"/><generator class="assigned"/></id>
<property name="itemNumber" column="`Item #`"/>
...
</class>]]></programlisting>
</sect1>
<sect1 id="mapping-alternatives">
<title>Metadata 대안들</title>
<para>
XML은 모든 사람들을 위한 것이 아니지만, Hibernate에서 O/R 매핑 메타데이터를 정의하는 몇몇 대안적인 방법들이 존재한다.
</para>
<sect2 id="mapping-xdoclet">
<title>XDoclet 마크업 사용하기</title>
<para>
많은 Hibernate 사용자들은 XDoclet <literal>@hibernate.tags</literal>를 사용하여 소스 코드 속에
직접 매핑 정보를 삽입시키는 것을 선호한다. 우리는 이 문서에서 이 접근법을 다루지 않을 것이다. 왜냐하면 그것은
엄격하게는 XDoclet의 부분으로 간주되기 때문이다. 하지만 우리는 XDoclet 매핑들을 가진 <literal>Cat</literal>
클래스에 관한 다음 예제를 포함한다.
</para>
<programlisting><![CDATA[package eg;
import java.util.Set;
import java.util.Date;
/**
* @hibernate.class
* table="CATS"
*/
public class Cat {
private Long id; // identifier
private Date birthdate;
private Cat mother;
private Set kittens
private Color color;
private char sex;
private float weight;
/*
* @hibernate.id
* generator-class="native"
* column="CAT_ID"
*/
public Long getId() {
return id;
}
private void setId(Long id) {
this.id=id;
}
/**
* @hibernate.many-to-one
* column="PARENT_ID"
*/
public Cat getMother() {
return mother;
}
void setMother(Cat mother) {
this.mother = mother;
}
/**
* @hibernate.property
* column="BIRTH_DATE"
*/
public Date getBirthdate() {
return birthdate;
}
void setBirthdate(Date date) {
birthdate = date;
}
/**
* @hibernate.property
* column="WEIGHT"
*/
public float getWeight() {
return weight;
}
void setWeight(float weight) {
this.weight = weight;
}
/**
* @hibernate.property
* column="COLOR"
* not-null="true"
*/
public Color getColor() {
return color;
}
void setColor(Color color) {
this.color = color;
}
/**
* @hibernate.set
* inverse="true"
* order-by="BIRTH_DATE"
* @hibernate.collection-key
* column="PARENT_ID"
* @hibernate.collection-one-to-many
*/
public Set getKittens() {
return kittens;
}
void setKittens(Set kittens) {
this.kittens = kittens;
}
// addKitten not needed by Hibernate
public void addKitten(Cat kitten) {
kittens.add(kitten);
}
/**
* @hibernate.property
* column="SEX"
* not-null="true"
* update="false"
*/
public char getSex() {
return sex;
}
void setSex(char sex) {
this.sex=sex;
}
}]]></programlisting>
<para>
XDoclet과 ibernate에 관한 추가 예제들은 Hibernate 웹 사이트를 보라.
</para>
</sect2>
<sect2 id="mapping-annotations" revision="2">
<title>JDK 5.0 Annotations 사용하기</title>
<para>
JDK 5.0은 언어 레벨에서 XDoclet-스타일의 주석들, type-safe와 컴파일 시 체킹을 도입했다. 이 메커니즘은 XDoclet
주석들 보다 더 강력하며 도구들과 IDE들에 의해 더 좋게 지원된다. 예를 들어 IntelliJ IDEA는 JDK 5.0 주석들에 대한
자동-완성 기능과 구문 강조를 지원한다. EJB 명세서의 새로운 개정판(JSR-220)은 엔티티 빈즈에 대한 프라이머리 메타데이터
메커니즘으로서 JDK 5.0 Annotations을 사용한다. Hibernate3는 JSR-220(영속 API)의 <literal>EntityManager</literal>
구현하고, 매핑 메타데이터에 대한 지원은 별도의 내려받기로서 <emphasis>Hibernate Annotations</emphasis> 패키지를
통해 이용 가능하다. EJB3 (JSR-220)과 Hibernate3 metadata 양자가 지원된다.
</para>
<para>
다음은 EJB 엔티티 빈으로서 주석이 붙은 POJO 클래스에 관한 예제이다:
</para>
<programlisting><![CDATA[@Entity(access = AccessType.FIELD)
public class Customer implements Serializable {
@Id;
Long id;
String firstName;
String lastName;
Date birthday;
@Transient
Integer age;
@Embedded
private Address homeAddress;
@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="CUSTOMER_ID")
Set<Order> orders;
// Getter/setter and business methods
}]]></programlisting>
<para>
JDK 5.0 Annotations(그리고 JSR-220)에 대한 지원은 여전히 작업이 진행 중이고 완성되지 않았음을 노트하라. 상세한 것은
Hibernate Anotations를 참조하라.
</para>
</sect2>
</sect1>
<sect1 id="mapping-generated" revision="1">
<title>산출되는 프로퍼티들</title>
<para>
산출되는 프로퍼티들은 데이터베이스에 의해 산출되는 그것들의 값들을 갖는 프로퍼티들이다. 전형적으로,
Hibernate 어플리케이션들은 데이터베이스가 값들을 생성시켰던 임의의 프로퍼티들을 포함하는 객체들을
<literal>갱신</literal>시킬 필요가 있었다.하지만 generated로 마크된 프로퍼티들은 어플리케이션으로
하여금 이 책임을 Hibernate에게 위임시키도록 한다. 본질적으로 Hibernate가 산출되는 프로퍼티들을 정의했던 엔티티에
대해 SQL INSERT 또는 UPDATE 명령을 내릴 때마다 바로 직후에 산출되는 값들을 검색하기 위해 하나의 select 명령을
내린다.
</para>
<para>
generated로 마크된 프로퍼티들은 부가적으로 inser 가능하지 않아야 하고 update 불가능해야 한다. 오직
Properties marked as generated must additionally be non-insertable and non-updateable.
<xref linkend="mapping-declaration-version">versions</xref>,
<xref linkend="mapping-declaration-timestamp">timestamps</xref>, 그리고
<xref linkend="mapping-declaration-property">단순 프로퍼티들</xref> 만이 generated로
마크될 수 있다.
</para>
<para>
<literal>never</literal> (디폴트) - 는 주어진 프로퍼티 값이 데이터베이스 내에 생성되지 않을 것임을 의미한다.
</para>
<para>
<literal>insert</literal> - 는 주어진 프로퍼티 값이 insert 시에 생성되지만, 차후의 업데이트들에서 다시
생성되지 않을 것임을 기술한다. 생성-날짜와 같은 것들이 이 카테고리 내로 포함될 것이다. 비록
<xref linkend="mapping-declaration-version">version</xref>
<xref linkend="mapping-declaration-timestamp">timestamp</xref> 프로퍼티들이 생성되는 것으로서
마크될 수 있을 지라도, 이 옵션은 거기서 이용 불가능함을 노트하라...
</para>
<para>
<literal>always</literal> - 는 프로퍼티 값이 insert 시와 update 시 모두에 생성됨을 기술한다.
</para>
</sect1>
<sect1 id="mapping-database-object">
<title>보조 데이터베이스 객체들</title>
<para>
Hibernate 매핑 파일들 내에 사용자 스키마를 완전하게 정의하기 위한 능력을 제공하기 위해서,
Hibernate의 스키마 방출 도구들과 함께 임의적인 데이터베이스 객체들에 대한 CREATE와 DROP을 허용해준다.
비록 트리거들 또는 내장 프로시저들과 같은 것들을 생성시키고 드롭시키기 이해 특별히 고안되었을지라도
하나의 <literal>java.sql.Statement.execute()</literal> 메소드를 통해 실행될 수 있는 SQL 명령이
여기서 유효하다(ALTERs, INSERTS, 기타). 보조 데0이터베이스 객체들을 정의하는 두 가지 모드들이 본질적으로
존재한다...
</para>
<para>
첫 번째 모드는 매핑 파일 바깥에서 CREATE 및 DROP 명령들을 명시적으로 나열하는 것이다:
</para>
<programlisting><![CDATA[<hibernate-mapping>
...
<database-object>
<create>CREATE TRIGGER my_trigger ...</create>
<drop>DROP TRIGGER my_trigger</drop>
</database-object>
</hibernate-mapping>]]></programlisting>
<para>
두번째 모드는 CREATE 및 DROP 명령들을 생성시키는 방법을 알고 있는 하나의 맞춤 클래스를 제공하는 것이다.
이 맞춤 클래스는 <literal>org.hibernate.mapping.AuxiliaryDatabaseObject</literal>
인터페이스를 구현해야 한다.
</para>
<programlisting><![CDATA[<hibernate-mapping>
...
<database-object>
<definition class="MyTriggerDefinition"/>
</database-object>
</hibernate-mapping>]]></programlisting>
<para>
덧붙여 이들 데이터베이스 객체들은 어떤 dialect들이 사용될 때 그것들이 단지 적용될 수 있도록 선택적으로
변동될 수 있다.
</para>
<programlisting><![CDATA[<hibernate-mapping>
...
<database-object>
<definition class="MyTriggerDefinition"/>
<dialect-scope name="org.hibernate.dialect.Oracle9Dialect"/>
<dialect-scope name="org.hibernate.dialect.OracleDialect"/>
</database-object>
</hibernate-mapping>]]></programlisting>
</sect1>
</chapter>