Tuesday, May 13, 2008

HIBERNATE - Relational Persistence for Idiomatic Java - 7

HIBERNATE - Relational Persistence for Idiomatic Java
Hibernate Reference Documentation
Hibernateレファレンスドキュメンテーション
3.2.2

Table of Contents(コンテンツテーブル)
Preface(序文)
1. Introduction to Hibernate(Hibernateの紹介)
2. Architecture(アーキテクチャ)
3. Configuration(設定)
4. Persistent Classes永続クラス
5. Basic O/R Mapping(基本的なO/Rマッピング)
6. Collection Mappingコレクションのマッピング
7. Association Mappings(関連マッピング)
7.1. Introduction(紹介)
7.2. Unidirectional associations(単方向関連)
7.2.1. many to one(多対一)
7.2.2. one to one(一対一)
7.2.3. one to many(一対多)
7.3. Unidirectional associations with join tables(結合テーブルを使った単方向関連)
7.3.1. one to many(一対多)
7.3.2. many to one(多対一)
7.3.3. one to one(一対一)
7.3.4. many to many(多対多)
7.4. Bidirectional associations(双方向関連)
7.4.1. one to many / many to one(一対多/多対一)
7.4.2. one to one(一対一)
7.5. Bidirectional associations with join tables(結合テーブルを使った双方向関連)
7.5.1. one to many / many to one(一対多/多対一)
7.5.2. one to one(一対一)
7.5.3. many to many(多対多)
7.6. More complex association mappings(より複雑な関連マッピング)

Chapter 7. Association Mappings(7章:関連マッピング)
7.1. Introduction(紹介)
Association mappings are the often most difficult thing to get right. In this section we'll go through the canonical cases one by one, starting with unidirectional mappings, and then considering the bidirectional cases. We'll use Person and Address in all the examples.
関連マッピングはしばしば理解が最も難しいものになります。この章では、基本的な一つ一つのケースについて述べます。単方向のマッピングから始め、それから双方向のケースについて考えていきます。例として、PersonAddressを用います。
We'll classify associations by whether or not they map to an intervening join table, and by multiplicity.
関連は、結合テーブルを入れるかかどうかと、多重度によって分類することにします。
Nullable foreign keys are not considered good practice in traditional data modelling, so all our examples use not null foreign keys. This is not a requirement of Hibernate, and the mappings will all work if you drop the nullability constraints.
すべての例でnot nullの外部キーを使用します。これはHibernateの要件ではありません。not null制約を外したとしても、マッピングは問題なく動作します。
7.2. Unidirectional associations(単方向関連)
7.2.1. many to one(多対一)
unidirectional many-to-one association is the most common kind of unidirectional association.
単方向多対一関連は単方向関連の中で最も一般的なものです。
<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <many-to-one name="address" 
        column="addressId"
        not-null="true"/>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
</class>

create table Person ( personId bigint not null primary key, addressId bigint not null )
create table Address ( addressId bigint not null primary key )
        
7.2.2. one to one(一対一)
unidirectional one-to-one association on a foreign key is almost identical. The only difference is the column unique constraint.
外部キーの単方向一対一関連はほとんど同じものです。唯一違うのは、カラムのユニークな制約です。
<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <many-to-one name="address" 
        column="addressId" 
        unique="true"
        not-null="true"/>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
</class>

create table Person ( personId bigint not null primary key, addressId bigint not null unique )
create table Address ( addressId bigint not null primary key )
        
unidirectional one-to-one association on a primary key usually uses a special id generator. (Notice that we've reversed the direction of the association in this example.)
主キーの単方向一対一関連は通常、特別なIDジェネレータを使います。(この例では関連の方向が逆になっていることに注意してください)
<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
</class>

<class name="Address">
    <id name="id" column="personId">
        <generator class="foreign">
            <param name="property">person</param>
        </generator>
    </id>
    <one-to-one name="person" constrained="true"/>
</class>

create table Person ( personId bigint not null primary key )
create table Address ( personId bigint not null primary key )
        
7.2.3. one to many(一対多)
unidirectional one-to-many association on a foreign key is a very unusual case, and is not really recommended.
外部キーの単方向一対多関連はとても特殊なケースで、あまり推奨されていません。
<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <set name="addresses">
        <key column="personId" 
            not-null="true"/>
        <one-to-many class="Address"/>
    </set>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
</class>

create table Person ( personId bigint not null primary key )
create table Address ( addressId bigint not null primary key, personId bigint not null )
        
We think it's better to use a join table for this kind of association.
このような関連のために結合テーブルを使うことをお薦めします。
7.3. Unidirectional associations with join tables(結合テーブルを使った単方向関連)
7.3.1. one to many(一対多)
unidirectional one-to-many association on a join table is much preferred. Notice that by specifying unique="true", we have changed the multiplicity from many-to-many to one-to-many.
結合テーブルを使った単方向一対多関連はより好ましいです。unique="true"の指定により、多重度が多対多から一対多に変わったことに注意して下さい。
<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <set name="addresses" table="PersonAddress">
        <key column="personId"/>
        <many-to-many column="addressId"
            unique="true"
            class="Address"/>
    </set>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
</class>

create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId not null, addressId bigint not null primary key )
create table Address ( addressId bigint not null primary key )
        
7.3.2. many to one(多対一)
unidirectional many-to-one association on a join table is quite common when the association is optional.
結合テーブルの単方向多対一関連は関連が任意であるときに非常に一般的なものです。
<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <join table="PersonAddress" 
        optional="true">
        <key column="personId" unique="true"/>
        <many-to-one name="address"
            column="addressId" 
            not-null="true"/>
    </join>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
</class>

create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null primary key, addressId bigint not null )
create table Address ( addressId bigint not null primary key )
        
7.3.3. one to one(一対一)
unidirectional one-to-one association on a join table is extremely unusual, but possible.
結合テーブルの単方向一対一関連は、本当に特殊ですが不可能ではありません。
<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <join table="PersonAddress" 
        optional="true">
        <key column="personId" 
            unique="true"/>
        <many-to-one name="address"
            column="addressId" 
            not-null="true"
            unique="true"/>
    </join>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
</class>

create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null primary key, addressId bigint not null unique )
create table Address ( addressId bigint not null primary key )
        
7.3.4. many to many(多対多)
Finally, we have a unidirectional many-to-many association.
最後に、単方向多対多関連を示します。
<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <set name="addresses" table="PersonAddress">
        <key column="personId"/>
        <many-to-many column="addressId"
            class="Address"/>
    </set>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
</class>

create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null, addressId bigint not null, primary key (personId, addressId) )
create table Address ( addressId bigint not null primary key )
        
7.4. Bidirectional associations(双方向関連)
7.4.1. one to many / many to one(一対多/多対一)
bidirectional many-to-one association is the most common kind of association. (This is the standard parent/child relationship.)
双方向多対一関連は最も一般的な関連です。(標準的な親子関係です)
<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <many-to-one name="address" 
        column="addressId"
        not-null="true"/>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
    <set name="people" inverse="true">
        <key column="addressId"/>
        <one-to-many class="Person"/>
    </set>
</class>

create table Person ( personId bigint not null primary key, addressId bigint not null )
create table Address ( addressId bigint not null primary key )
        
If you use a List (or other indexed collection) you need to set the key column of the foreign key to not null, and let Hibernate manage the association from the collections side to maintain the index of each element (making the other side virtually inverse by setting update="false" and insert="false"):
List(または他のインデックス付きのコレクション)を使うなら、外部キーのkeyカラムをnot nullに設定し、コレクション側が各要素のインデックスをメンテナンスするように、関連を扱う必要があります(update="false"かつinsert="false"と設定して、反対側を仮想的にinverseにします):
<class name="Person">
   <id name="id"/>
   ...
   <many-to-one name="address"
      column="addressId"
      not-null="true"
      insert="false"
      update="false"/>
</class>

<class name="Address">
   <id name="id"/>
   ...
   <list name="people">
      <key column="addressId" not-null="true"/>
      <list-index column="peopleIdx"/>
      <one-to-many class="Person"/>
   </list>
</class>
It is important that you define not-null="true" on the <key> element of the collection mapping if the underlying foreign key column is NOT NULL. Don't only declare not-null="true" on a possible nested <column> element, but on the <key> element.
もし外部キーカラムがNOT NULLであるならば、コレクションマッピングの<key>要素をnot-null="true"にすることは重要です。入れ子になった<column>要素だけではなく、<key>要素もnot-null="true"と定義しないようにしてください。
7.4.2. one to one(一対一)
bidirectional one-to-one association on a foreign key is quite common.
外部キーの双方向一対一関連は非常に一般的です。
<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <many-to-one name="address" 
        column="addressId" 
        unique="true"
        not-null="true"/>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
   <one-to-one name="person" 
        property-ref="address"/>
</class>

create table Person ( personId bigint not null primary key, addressId bigint not null unique )
create table Address ( addressId bigint not null primary key )
        
bidirectional one-to-one association on a primary key uses the special id generator.
主キーの双方向一対一関連は特殊なIDジェネレータを使います。
<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <one-to-one name="address"/>
</class>

<class name="Address">
    <id name="id" column="personId">
        <generator class="foreign">
            <param name="property">person</param>
        </generator>
    </id>
    <one-to-one name="person" 
        constrained="true"/>
</class>

create table Person ( personId bigint not null primary key )
create table Address ( personId bigint not null primary key )
        
7.5. Bidirectional associations with join tables(結合テーブルを使った双方向関連)
7.5.1. one to many / many to one(一対多/多対一)
bidirectional one-to-many association on a join table. Note that the inverse="true" can go on either end of the association, on the collection, or on the join.
結合テーブルの双方向一対多関連です。inverse="true"が関連端、コレクション、結合のいずれかに設定できることに注意してください。
<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <set name="addresses" 
        table="PersonAddress">
        <key column="personId"/>
        <many-to-many column="addressId"
            unique="true"
            class="Address"/>
    </set>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
    <join table="PersonAddress" 
        inverse="true" 
        optional="true">
        <key column="addressId"/>
        <many-to-one name="person"
            column="personId"
            not-null="true"/>
    </join>
</class>

create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null, addressId bigint not null primary key )
create table Address ( addressId bigint not null primary key )
        
7.5.2. one to one(一対一)
bidirectional one-to-one association on a join table is extremely unusual, but possible.
結合テーブルの双方向一対一関連は非常に特殊ですが、可能です。
<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <join table="PersonAddress" 
        optional="true">
        <key column="personId" 
            unique="true"/>
        <many-to-one name="address"
            column="addressId" 
            not-null="true"
            unique="true"/>
    </join>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
    <join table="PersonAddress" 
        optional="true"
        inverse="true">
        <key column="addressId" 
            unique="true"/>
        <many-to-one name="person"
            column="personId" 
            not-null="true"
            unique="true"/>
    </join>
</class>

create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null primary key, addressId bigint not null unique )
create table Address ( addressId bigint not null primary key )
        
7.5.3. many to many(多対多)
Finally, we have a bidirectional many-to-many association.
最後に、双方向多対多関連を示します。
<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <set name="addresses" table="PersonAddress">
        <key column="personId"/>
        <many-to-many column="addressId"
            class="Address"/>
    </set>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
    <set name="people" inverse="true" table="PersonAddress">
        <key column="addressId"/>
        <many-to-many column="personId"
            class="Person"/>
    </set>
</class>

create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null, addressId bigint not null, primary key (personId, addressId) )
create table Address ( addressId bigint not null primary key )
        
7.6. More complex association mappings(より複雑な関連マッピング)
More complex association joins are extremely rare. Hibernate makes it possible to handle more complex situations using SQL fragments embedded in the mapping document. For example, if a table with historical account information data definesaccountNumbereffectiveEndDate and effectiveStartDatecolumns, mapped as follows:
より複雑な関連結合は 極めて稀です。マッピングドキュメントにSQL文を埋め込むことで、さらに複雑な状況を扱うことができます。例えば、accountNumber, effectiveEndDate, effectiveStartDateカラムを持つaccount(口座)情報の履歴を扱うテーブルは、以下のようにマッピングします。
<properties name="currentAccountKey">
    <property name="accountNumber" type="string" not-null="true"/>
    <property name="currentAccount" type="boolean">
        <formula>case when effectiveEndDate is null then 1 else 0 end</formula>
    </property>
</properties>
<property name="effectiveEndDate" type="date"/>
<property name="effectiveStateDate" type="date" not-null="true"/>
Then we can map an association to the current instance (the one with nulleffectiveEndDate) using:
そして、関連を 現時点のインスタンス(effectiveEndDatenullであるもの)にマッピングします。以下のようになります:
<many-to-one name="currentAccountInfo" 
        property-ref="currentAccountKey"
        class="AccountInfo">
    <column name="accountNumber"/>
    <formula>'1'</formula>
</many-to-one>
In a more complex example, imagine that the association between Employee andOrganization is maintained in an Employment table full of historical employment data. Then an association to the employee's most recent employer (the one with the most recent startDate) might be mapped this way:
さらに複雑な例では、Employee(従業員)とOrganization(組織)間の関連がEmployment(雇用)テーブルで保持される場合を想像してください。このテーブルには雇用データの履歴がすべて含まれます。すると従業員の 最も最近の雇用者を表す関連(最も最近のstartDateを持つもの)は、このようにマッピングできます:
<join>
    <key column="employeeId"/>
    <subselect>
        select employeeId, orgId 
        from Employments 
        group by orgId 
        having startDate = max(startDate)
    </subselect>
    <many-to-one name="mostRecentEmployer" 
            class="Organization" 
            column="orgId"/>
</join>
You can get quite creative with this functionality, but it is usually more practical to handle these kinds of cases using HQL or a criteria query.
この機能は非常に強力です。しかしこのような場合、普通はHQLcriteriaクエリを使う方がより実践的です。

No comments:

Post a Comment