mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-03-01 07:19:15 +00:00
git-svn-id: https://svn.jboss.org/repos/hibernate/core/branches/Branch_3_2@11779 1b8cb986-b30d-0410-93ca-fae66ebed9b2
274 lines
11 KiB
XML
274 lines
11 KiB
XML
<chapter id="xml">
|
|
<title>XML 매핑</title>
|
|
|
|
<para><emphasis>
|
|
이것은 Hibernate3.0에서 실험적인 특징이고 매우 활동적으로 개발 중에 있음을 노트하라.
|
|
</emphasis></para>
|
|
|
|
<sect1 id="xml-intro" revision="1">
|
|
<title>XML 데이터로 작업하기</title>
|
|
|
|
<para>
|
|
Hibernate는 당신이 영속 POJO들로 작업하는 것과 아주 동일한 방법으로 영속 XML 데이터에 작업하도록 해준다. 파싱된 XML 트리는
|
|
단지 객체 레벨에서 관계형 데이터를 나타내는 또 다른 방법으로 간주될 수 있다. 하나의 파싱된 XML 트리는 POJO들 대신, 객체 레벨에서
|
|
관계형 데이터를 표현하는 단지 또 다른 방법으로 간주될 수 있다.
|
|
</para>
|
|
|
|
<para>
|
|
Hibernate는 XML 트리들을 처리하는 API로서 dom4j를 지원한다. 당신은 데이터베이스로부터 dom4j 트리들을 검색하고 당신이 그 트리를
|
|
데이터베이스와 자동적으로 동기화시키기 위해 어떤 변경을 행하도록 하는 질의들을 작성할 수 있다. 당신은 심지어 XML 문서를 취하고,
|
|
dom4j를 사용하여 그것을 파싱하고, Hibernate의 다음 기본적인 오퍼레이션들 중 어떤 것으로서 그것을 데이터베이스에 저장시킬 수 있다:
|
|
<literal>persist(), saveOrUpdate(), merge(), delete(), replicate()</literal>(merging(병합)은 아직 지원되지
|
|
않는다).
|
|
</para>
|
|
|
|
<para>
|
|
이 특징은 데이터 가져오기/내보내기,JMS 또는 SOAP 그리고 XSLT-기반의 레포팅을 통한 엔티티 데이터의 구체화를 포함하는 많은
|
|
어플리케이션들을 갖는다.
|
|
</para>
|
|
|
|
<para>
|
|
하나의 매핑은 클래스들의 프로퍼티들과 XML 문서의 노드들을 데이터베이스로 동시에 매핑시키는데 사용될 수 있거나, 만일 매핑할 클래스가
|
|
존재하지 않을 경우, 그것은 단지 XML을 매핑시키는데 사용될 수도 있다.
|
|
</para>
|
|
|
|
<sect2 id="xml-intro-mapping">
|
|
<title>XML과 클래스 매핑을 함께 지정하기</title>
|
|
|
|
<para>
|
|
다음은 POJO와 XML을 동시에 매핑시키는 예제이다 :
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<class name="Account"
|
|
table="ACCOUNTS"
|
|
node="account">
|
|
|
|
<id name="accountId"
|
|
column="ACCOUNT_ID"
|
|
node="@id"/>
|
|
|
|
<many-to-one name="customer"
|
|
column="CUSTOMER_ID"
|
|
node="customer/@id"
|
|
embed-xml="false"/>
|
|
|
|
<property name="balance"
|
|
column="BALANCE"
|
|
node="balance"/>
|
|
|
|
...
|
|
|
|
</class>]]></programlisting>
|
|
</sect2>
|
|
|
|
<sect2 id="xml-onlyxml">
|
|
<title>XML 매핑만을 지정하기</title>
|
|
|
|
<para>
|
|
다음은 POJO 클래스가 존재하지 않는 예제이다:
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<class entity-name="Account"
|
|
table="ACCOUNTS"
|
|
node="account">
|
|
|
|
<id name="id"
|
|
column="ACCOUNT_ID"
|
|
node="@id"
|
|
type="string"/>
|
|
|
|
<many-to-one name="customerId"
|
|
column="CUSTOMER_ID"
|
|
node="customer/@id"
|
|
embed-xml="false"
|
|
entity-name="Customer"/>
|
|
|
|
<property name="balance"
|
|
column="BALANCE"
|
|
node="balance"
|
|
type="big_decimal"/>
|
|
|
|
...
|
|
|
|
</class>]]></programlisting>
|
|
|
|
<para>
|
|
이 매핑은 dom4j 트리로서 또는 프로퍼티 name/value 쌍들(java <literal>Map</literal>들)의 그래프로서 데이터에
|
|
접근하는 것을 당신에게 허용해준다. 프로퍼티 이름들은 HQL 질의들 내에서 참조될 수도 있는 순수하게 논리적인 구조체들이다.
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
</sect1>
|
|
|
|
<sect1 id="xml-mapping" revision="1">
|
|
<title>XML 매핑 메타데이터</title>
|
|
|
|
<para>
|
|
많은 Hibernate 매핑 요소들은 <literal>node</literal> 속성을 수용한다. 이것은 당신이 프로퍼티 또는 엔티티 데이터를 소유하는
|
|
XML 속성이나 요소의 이름을 지정하도록 한다. <literal>node</literal> 속성의 포맷은 다음 중 하나이어야 한다:
|
|
</para>
|
|
|
|
<itemizedlist spacing="compact">
|
|
<listitem>
|
|
<para><literal>"element-name"</literal> - 명명된 XML 요소로 매핑시킨다</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><literal>"@attribute-name"</literal> - 명명된 XML 속성으로 매핑시킨다 </para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><literal>"."</literal> - 부모 요소로 매핑 시킨다</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<literal>"element-name/@attribute-name"</literal> -
|
|
명명된 요소의 명명된 속성으로 매핑시킨다
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>
|
|
콜렉션들과 단일 값 콜렉션들의 경우, 추가적인 <literal>embed-xml</literal> 속성이 존재한다. 만일 <literal>embed-xml="true"</literal>
|
|
일 경우, 연관된 엔티티(또는 value 타입을 가진 콜렉션)에 대한 디폴트 XML 트리는 그 연관을 소유하는 엔티티에 대한 XML 트리 속에
|
|
직접 삽입될 것이다. 그 밖의 경우 <literal>embed-xml="false"</literal> 일 경우, 참조된 식별자 값 만이 단일 포인트 연관들에
|
|
대해 나타날 것이고 콜렉션들은 단순히 전혀 나타나지 않을 것이다.
|
|
</para>
|
|
|
|
<para>
|
|
당신은 너무 많은 연관들에 대해 <literal>embed-xml="true"</literal>로 남겨두지 말도록 주의해야 한다. 왜냐하면 XML이
|
|
순환적으로 잘 처리하지 못하기 때문이다!
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<class name="Customer"
|
|
table="CUSTOMER"
|
|
node="customer">
|
|
|
|
<id name="id"
|
|
column="CUST_ID"
|
|
node="@id"/>
|
|
|
|
<map name="accounts"
|
|
node="."
|
|
embed-xml="true">
|
|
<key column="CUSTOMER_ID"
|
|
not-null="true"/>
|
|
<map-key column="SHORT_DESC"
|
|
node="@short-desc"
|
|
type="string"/>
|
|
<one-to-many entity-name="Account"
|
|
embed-xml="false"
|
|
node="account"/>
|
|
</map>
|
|
|
|
<component name="name"
|
|
node="name">
|
|
<property name="firstName"
|
|
node="first-name"/>
|
|
<property name="initial"
|
|
node="initial"/>
|
|
<property name="lastName"
|
|
node="last-name"/>
|
|
</component>
|
|
|
|
...
|
|
|
|
</class>]]></programlisting>
|
|
|
|
<para>
|
|
이 경우에, 우리는 실제 account 데이터가 아닌, account id들을 가진 콜렉션을 삽입시키기로 결정했다. 다음 HQL 질의:
|
|
</para>
|
|
|
|
<programlisting><![CDATA[from Customer c left join fetch c.accounts where c.lastName like :lastName]]></programlisting>
|
|
|
|
<para>
|
|
는 다음과 같은 데이터셋들을 반환할 것이다:
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<customer id="123456789">
|
|
<account short-desc="Savings">987632567</account>
|
|
<account short-desc="Credit Card">985612323</account>
|
|
<name>
|
|
<first-name>Gavin</first-name>
|
|
<initial>A</initial>
|
|
<last-name>King</last-name>
|
|
</name>
|
|
...
|
|
</customer>]]></programlisting>
|
|
|
|
<para>
|
|
만일 당신이 <literal><one-to-many></literal> 매핑에 대해 <literal>embed-xml="true"</literal>를 설정할 경우,
|
|
데이터는 다음과 같이 보일 수도 있다:
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<customer id="123456789">
|
|
<account id="987632567" short-desc="Savings">
|
|
<customer id="123456789"/>
|
|
<balance>100.29</balance>
|
|
</account>
|
|
<account id="985612323" short-desc="Credit Card">
|
|
<customer id="123456789"/>
|
|
<balance>-2370.34</balance>
|
|
</account>
|
|
<name>
|
|
<first-name>Gavin</first-name>
|
|
<initial>A</initial>
|
|
<last-name>King</last-name>
|
|
</name>
|
|
...
|
|
</customer>]]></programlisting>
|
|
|
|
</sect1>
|
|
|
|
|
|
<sect1 id="xml-manipulation" revision="1">
|
|
<title>XML 데이터 처리하기</title>
|
|
|
|
<para>
|
|
우리의 어플리케이션 내에서 XML 문서들을 다시 읽어들이고 업데이트 시키자. 우리는 dom4j 세션을 얻어서 이것을 행한다:
|
|
</para>
|
|
|
|
<programlisting><![CDATA[Document doc = ....;
|
|
|
|
Session session = factory.openSession();
|
|
Session dom4jSession = session.getSession(EntityMode.DOM4J);
|
|
Transaction tx = session.beginTransaction();
|
|
|
|
List results = dom4jSession
|
|
.createQuery("from Customer c left join fetch c.accounts where c.lastName like :lastName")
|
|
.list();
|
|
for ( int i=0; i<results.size(); i++ ) {
|
|
//add the customer data to the XML document
|
|
Element customer = (Element) results.get(i);
|
|
doc.add(customer);
|
|
}
|
|
|
|
tx.commit();
|
|
session.close();]]></programlisting>
|
|
|
|
<programlisting><![CDATA[Session session = factory.openSession();
|
|
Session dom4jSession = session.getSession(EntityMode.DOM4J);
|
|
Transaction tx = session.beginTransaction();
|
|
|
|
Element cust = (Element) dom4jSession.get("Customer", customerId);
|
|
for ( int i=0; i<results.size(); i++ ) {
|
|
Element customer = (Element) results.get(i);
|
|
//change the customer name in the XML and database
|
|
Element name = customer.element("name");
|
|
name.element("first-name").setText(firstName);
|
|
name.element("initial").setText(initial);
|
|
name.element("last-name").setText(lastName);
|
|
}
|
|
|
|
tx.commit();
|
|
session.close();]]></programlisting>
|
|
|
|
<para>
|
|
XML 기반의 데이터 가져오기/내보내기를 구현하는데 이 특징과 Hibernate의 <literal>replicate()</literal> 오퍼레이션을
|
|
결합시키는 것이 매우 유용하다.
|
|
</para>
|
|
|
|
</sect1>
|
|
|
|
</chapter>
|
|
|