mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-03-03 08:19:15 +00:00
git-svn-id: https://svn.jboss.org/repos/hibernate/trunk/Hibernate3/doc@9072 1b8cb986-b30d-0410-93ca-fae66ebed9b2
3141 lines
180 KiB
XML
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><class></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><hibernate-mapping></literal> 요소에 의해 지정된
|
|
스키마 이름을 오버라이드 시킨다.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="class6">
|
|
<para>
|
|
<literal>catalog</literal> (옵션): 루트 <literal><hibernate-mapping></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><union-subclass></literal> 계층 구조들 내에서
|
|
abstract 슈퍼클래스들을 마크하는데 사용된다.
|
|
</para>
|
|
</callout>
|
|
</calloutlist>
|
|
</programlistingco>
|
|
|
|
<para>
|
|
명명된 영속 클래스가 인터페이스가 되는 것은 완전히 수용가능하다. 그런 다음 당신은 <literal><subclass></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><class></literal> 선언 내부에서 <literal><subclass></literal>
|
|
또는 <literal><joined-subclass></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><subclass></literal> 또는 <literal><joined-subclass></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><subselect></literal>는 속성과 내포된 매핑 요소 양자로서 이용 가능하다.
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-declaration-id" revision="4">
|
|
<title>id</title>
|
|
|
|
<para>
|
|
매핑된 클래스들은 데이터베이스 테이블의 프라이머리 키 컬럼을 선언<emphasis>해야 한다</emphasis>. 대부분의 클래스들은 또한 인스턴스의 유일 식별자를 소유하는
|
|
자바빈즈-스타일 프로퍼티를 가질 것이다. <literal><id></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><composite-id></literal>
|
|
선언이 존재한다. 우리는 그 밖의 어떤것에 대한 그것의 사용에 대해 강력하게 반대한다.
|
|
</para>
|
|
|
|
<sect3 id="mapping-declaration-id-generator" revision="2">
|
|
<title>Generator</title>
|
|
|
|
<para>
|
|
선택적인 <literal><generator></literal> 자식 요소는 영속 클래스의 인스턴스들에 대한 유일 식별자들을 생성시키는데 사용되는
|
|
자바 클래스를 명명한다. 만일 임의의 파라미터들이 생성기 인스턴스를 구성하거나 초기화 시키는데 필요할 경우, 그것들은 <literal><param></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><generator></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><one-to-one></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><generator></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><composite-id></literal> 요소는 자식 요소들로서 <literal><key-property></literal>
|
|
프로퍼티 매핑과 <literal><key-many-to-one></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><composite-id></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>을
|
|
구현해야 한다. 이 접근법의 단점은 아주 명백한—코드 중복이다.
|
|
</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><discriminator></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><class></literal> 요소와
|
|
<literal><subclass></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><version></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><timestamp></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><timestamp></literal>는 <literal><version type="timestamp"></literal>과
|
|
같음을 노트하라. 그리고 <literal><timestamp use-db="true"></literal>는
|
|
<literal><version type="dbtimestamp"></literal>과 같다
|
|
</para>
|
|
</sect2>
|
|
|
|
|
|
<sect2 id="mapping-declaration-property" revision="4">
|
|
<title>프로퍼티</title>
|
|
|
|
<para>
|
|
<literal><property></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><column></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><formula></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><column></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><properties></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><natural-id></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><component></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><property></literal> 태그들은 자식 클래스의 프로퍼티들을 테이블 컬럼들로 매핑시킨다.
|
|
</para>
|
|
|
|
<para>
|
|
<literal><component></literal> 요소는 컴포넌트 클래스의 프로퍼티를 포함하는 엔티티에 대한 참조로서 매핑시키는
|
|
<literal><parent></literal> 서브요소를 허용한다.
|
|
</para>
|
|
|
|
<para>
|
|
<literal><dynamic-component></literal> 요소는 컴포넌트로서 매핑될<literal>Map</literal>을 허용한다.
|
|
여기서 프로퍼티 이름들은 map의 키들을 참조한다. <xref linkend="components-dynamic"/>을 보라.
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-declaration-properties" revision="2">
|
|
<title>properties</title>
|
|
|
|
<para>
|
|
<literal><properties></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><properties></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><subclass></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><version></literal>
|
|
프로퍼티와 <literal><id></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><joined-subclass></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><key></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><class></literal> 선언을 가진 각각의 클래스를
|
|
간단히 매핑시킬 수 있다. 하지만 당신이 다형성 연관관계들(예를 들면 당신의 계층구조의 슈퍼클래스에 대한 연관)을 사용하고자 원할
|
|
경우, 당신은 <literal><union-subclass></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><join></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><hibernate-mapping></literal> 요소에
|
|
의해 지정된 스키마 이름을 오버라이드 시킨다
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="join3">
|
|
<para>
|
|
<literal>catalog</literal> (옵션): 루트 <literal><hibernate-mapping></literal> 요소에
|
|
의해 지정된 카타록 이름을 오버라이드 시킨다.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="join4">
|
|
<para>
|
|
<literal>fetch</literal> (옵션 - 디폴트는 <literal>join</literal>):
|
|
<literal>join</literal>으로 설정될 경우, 디폴트로 Hibernate는 하나의 클래스 또는 그것의 슈퍼 클래스들에 의해
|
|
정의된 <literal><join></literal>을 검색하는데 inner join을 사용하고 서브클래스에 의해 정의된
|
|
<literal><join></literal>을 검색하는데 outer join을 사용할 것이다. 만일 <literal>select</literal>로
|
|
설정할 경우, Hibernate는 서브클래스 상에 정의된 <literal><join></literal>에 대해 sequential
|
|
select를 사용할 것이고, 그것은 한 행이 서브클래스의 인스턴스를 표현하는 것으로 판명되는 경우에만 명령이 내려질 것이다.
|
|
inner join들은 여전히 클래스와 그것의 슈퍼클래스들에 의해 정의된 <literal><join></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><key></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><column></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><key not-null="true"></literal>를 사용하여 그 키 컬럼을 선언<emphasis>해야 한다</emphasis>.
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-column" revision="4">
|
|
<title>column 요소와 formula 요소</title>
|
|
<para>
|
|
column 속성을 허용하는 임의의 매핑 요소는 대안적으로 하나의 <literal><column></literal> 서브요소를 수용할 것이다.
|
|
비슷하게 <literal><formula></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><any></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><class></literal>,
|
|
<literal><subclass></literal> 등을 사용한다.value 타입들의 경우 우리는 대개<literal>type</literal> 속성을 가진
|
|
<literal><property></literal>, <literal><component></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><column></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><type></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><typedef></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>
|
|
|