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(永続クラス)
6. Collection Mapping(コレクションのマッピング)
7. Association Mappings(関連マッピング)
8. Component Mapping(コンポーネントのマッピング)
8.1. Dependent objects(依存オブジェクト)
8.2. Collections of dependent objects(従属するオブジェクトのコレクション)
8.3. Components as Map indices(Mapのインデックスとしてのコンポーネント)
8.4. Components as composite identifiers(複合識別子としてのコンポーネント)
8.5. Dynamic components(動的コンポーネント)
Chapter 8. Component Mapping(第8章:コンポーネントのマッピング)
The notion of a component is re-used in several different contexts, for different purposes, throughout Hibernate.
コンポーネントの概念は、Hibernateを通して様々な状況の中で異なる目的のために再利用されます。
8.1. Dependent objects(依存オブジェクト)
A component is a contained object that is persisted as a value type, not an entity reference. The term "component" refers to the object-oriented notion of composition (not to architecture-level components). For example, you might model a person like this:
コンポーネントは、エンティティの参照ではなく値型として永続化された、包含されたオブジェクトです。コンポーネントという言葉については、コンポジションというオブジェクト指向の概念を参照してください(アーキテクチャレベルのコンポーネントではありません)。例えば、以下のPersonモデルのようなものです。
public class Person {
private java.util.Date birthday;
private Name name;
private String key;
public String getKey() {
return key;
}
private void setKey(String key) {
this.key=key;
}
public java.util.Date getBirthday() {
return birthday;
}
public void setBirthday(java.util.Date birthday) {
this.birthday = birthday;
}
public Name getName() {
return name;
}
public void setName(Name name) {
this.name = name;
}
......
......
}
public class Name {
char initial;
String first;
String last;
public String getFirst() {
return first;
}
void setFirst(String first) {
this.first = first;
}
public String getLast() {
return last;
}
void setLast(String last) {
this.last = last;
}
public char getInitial() {
return initial;
}
void setInitial(char initial) {
this.initial = initial;
}
}
Now Name may be persisted as a component of Person. Notice that Name defines getter and setter methods for its persistent properties, but doesn't need to declare any interfaces or identifier properties.
いま、NameはPersonのコンポーネントとして永続化することが出来ます。ここでNameは永続化属性に対してgetter、setterメソッドを定義しますが、インターフェイスや識別子プロパティを定義する必要がないことに注意して下さい。
Our Hibernate mapping would look like:
マッピング定義は以下のようになります。
<class name="eg.Person" table="person">
<id name="Key" column="pid" type="string">
<generator class="uuid"/>
</id>
<property name="birthday" type="date"/>
<component name="Name" class="eg.Name"> <!-- class attribute optional -->
<property name="initial"/>
<property name="first"/>
<property name="last"/>
</component>
</class>
The person table would have the columns pid, birthday, initial, first and last.
Personテーブルはpid、birthday、initial、first、lastカラムを持ちます。
Like all value types, components do not support shared references. In other words, two persons could have the same name, but the two person objects would contain two independent name ojects, only "the same" by value. The null value semantics of a component are ad hoc. When reloading the containing object, Hibernate will assume that if all component columns are null, then the entire component is null. This should be okay for most purposes.
全ての値型のように、コンポーネントは参照の共有をすることができません。言い換えると、二人のPersonは同じ名前を持つことができますが、二つのPersonオブジェクトは"値が同じだけ"の別々のnameオブジェクトを含んでいるということです。コンポーネントのnull値のセマンティクスは アドホックです。コンポーネントのオブジェクトを再読み込みする際、Hibernateはコンポーネントのすべてのカラムがnullであるならコンポーネント自体がnullであると考えます。これは大抵の場合問題ありません。
The properties of a component may be of any Hibernate type (collections, many-to-one associations, other components, etc). Nested components should not be considered an exotic usage. Hibernate is intended to support a very fine-grained object model.
コンポーネントの属性はどんなHibernateの型でも構いません(コレクション、many-to-one関連、他のコンポーネントなど)。ネストされたコンポーネントは滅多に使わないと考えるべきではありません。Hibernateは非常にきめの細かいオブジェクトモデルをサポートするように意図されています。
The <component> element allows a <parent> subelement that maps a property of the component class as a reference back to the containing entity.
<component>要素は親エンティティへの逆参照として、コンポーネントクラスの属性をマッピングする<parent>サブ要素を使用できます。
<class name="eg.Person" table="person">
<id name="Key" column="pid" type="string">
<generator class="uuid"/>
</id>
<property name="birthday" type="date"/>
<component name="Name" class="eg.Name" unique="true">
<parent name="namedPerson"/> <!-- reference back to the Person -->
<property name="initial"/>
<property name="first"/>
<property name="last"/>
</component>
</class>
8.2. Collections of dependent objects(従属するオブジェクトのコレクション)
Collections of components are supported (eg. an array of type Name). Declare your component collection by replacing the <element> tag with a <composite-element> tag.
Hibernateはコンポーネントのコレクションをサポートしています(例えばName型の配列)。<element>タグを<composite-element>タグに取り替えることによりコンポーネントコレクションを宣言してください。
<set name="someNames" table="some_names" lazy="true">
<key column="id"/>
<composite-element class="eg.Name"> <!-- class attribute required -->
<property name="initial"/>
<property name="first"/>
<property name="last"/>
</composite-element>
</set>
Note: if you define a Set of composite elements, it is very important to implementequals() and hashCode() correctly.
注意: コンポジットエレメントのSetを定義したなら、equals()とhashCode()を正しく実装することが重要です。
Composite elements may contain components but not collections. If your composite element itself contains components, use the <nested-composite-element> tag. This is a pretty exotic case - a collection of components which themselves have components. By this stage you should be asking yourself if a one-to-many association is more appropriate. Try remodelling the composite element as an entity - but note that even though the Java model is the same, the relational model and persistence semantics are still slightly different.
コンポジットエレメントはコレクションを含まず、コンポーネントを含むこともあります。コンポジットエレメント自身がコンポーネントを含んでいる場合は<nested-composite-element>を使用してください。コンポーネントのコレクション自身がコンポーネントを持つというケースはめったにありません。この段階までに、one-to-many関連の方がより適切でないかと熟考してください。コンポジットエレメントをエンティティとして再度モデリングしてみてください。しかしこれはJavaのモデルとしては同じですが、リレーショナルモデルと永続動作はまだ若干異なることに注意してください。
Please note that a composite element mapping doesn't support null-able properties if you're using a <set>. Hibernate has to use each columns value to identify a record when deleting objects (there is no separate primary key column in the composite element table), which is not possible with null values. You have to either use only not-null properties in a composite-element or choose a <list>, <map>, <bag> or <idbag>.
もし<set>を使用するのであれば、コンポジットエレメントのマッピングがnull値が可能な属性をサポートしていないことに注意してください。Hibernateはオブジェクトを削除するとき、レコードを識別するためにそれぞれのカラムの値を使用する必要があるため、null値を持つことが出来ません(コンポジットエレメントテーブルには別の主キーカラムはありません)。コンポジットエレメントにnot-nullの属性のみを使用するか、または<list>、<map>、<bag>、<idbag>を選択する必要があります。
A special case of a composite element is a composite element with a nested <many-to-one> element. A mapping like this allows you to map extra columns of a many-to-many association table to the composite element class. The following is a many-to-many association from Order to Item where purchaseDate, price and quantity are properties of the association:
コンポジットエレメントの特別なケースとして、ネストされた<many-to-one>属性を持つコンポジットエレメントがあります。このマッピングは、コンポジットエレメントクラスを多対多関連テーブルの余分なカラムへマッピングします。次の例はOrderから、Itemへの多対多関連です。purchaseDate、price、quantityは関連の属性となります。
<class name="eg.Order" .... >
....
<set name="purchasedItems" table="purchase_items" lazy="true">
<key column="order_id">
<composite-element class="eg.Purchase">
<property name="purchaseDate"/>
<property name="price"/>
<property name="quantity"/>
<many-to-one name="item" class="eg.Item"/> <!-- class attribute is optional -->
</composite-element>
</set>
</class>
Of course, there can't be a reference to the purchae on the other side, for bidirectional association navigation. Remember that components are value types and don't allow shared references. A single Purchase can be in the set of an Order, but it can't be referenced by the Item at the same time.
もちろん、双方向関連のナビゲーションのために反対側からpurchaseへの参照を作ることは出来ません。コンポーネントは値型であり、参照を共有できないことを覚えておいてください。一つのPurchaseは一つのOrderのsetに存在できますが、同時にItemから参照することは出来ません。
Even ternary (or quaternary, etc) associations are possible:
3項関連(あるいは4項など)も可能です。
<class name="eg.Order" .... >
....
<set name="purchasedItems" table="purchase_items" lazy="true">
<key column="order_id">
<composite-element class="eg.OrderLine">
<many-to-one name="purchaseDetails class="eg.Purchase"/>
<many-to-one name="item" class="eg.Item"/>
</composite-element>
</set>
</class>
Composite elements may appear in queries using the same syntax as associations to other entities.
コンポジットエレメントは他のエンティティへの関連として、同じシンタックスを使っているクエリ内で使用できます。
8.3. Components as Map indices(Mapのインデックスとしてのコンポーネント)
The <composite-map-key> element lets you map a component class as the key of a Map. Make sure you override hashCode() and equals() correctly on the component class.
<composite-map-key>要素はMapのキーとしてコンポーネントクラスをマッピングします。コンポーネントクラス上でhashCode()とequals()を正確にオーバーライドしてください。
8.4. Components as composite identifiers(複合識別子としてのコンポーネント)
You may use a component as an identifier of an entity class. Your component class must satisfy certain requirements:
コンポーネントをエンティティクラスの識別子として使うことができます。コンポーネントクラスは以下の条件を満たす必要があります。
? It must implement java.io.Serializable.
java.io.Serializableを実装しなければなりません。
? It must re-implement equals() and hashCode(), consistently with the database's notion of composite key equality.
データベース上の複合キーの等価性と矛盾のないように、equals()とhashCode()を再実装しなければなりません。
Note: in Hibernate3, the second requirement is not an absolutely hard requirement of Hibernate. But do it anyway.
注意: Hibernate3において、2番目の条件は絶対的な条件ではありません。しかしとにかく条件を満たしてください。
You can't use an IdentifierGenerator to generate composite keys. Instead the application must assign its own identifiers.
複合キーを生成するためにIdentifierGeneratorを使用することはできません。代わりにアプリケーションが識別子を割り当てなくてはなりません。
Use the <composite-id> tag (with nested <key-property> elements) in place of the usual<id> declaration. For example, the OrderLine class has a primary key that depends upon the (composite) primary key of Order.
通常の<id>宣言の代わりに<composite-id>タグを(ネストされた<key-property>属性と共に)使います。以下の例では、OrderLineクラスはOrderの(複合)主キーに依存した主キーを持っています。
<class name="OrderLine">
<composite-id name="id" class="OrderLineId">
<key-property name="lineId"/>
<key-property name="orderId"/>
<key-property name="customerId"/>
</composite-id>
<property name="name"/>
<many-to-one name="order" class="Order"
insert="false" update="false">
<column name="orderId"/>
<column name="customerId"/>
</many-to-one>
....
</class>
Now, any foreign keys referencing the OrderLine table are also composite. You must declare this in your mappings for other classes. An association to OrderLine would be mapped like this:
このとき、OrderLineテーブルへ関連する外部キーもまた複合です。他のクラスのマッピングでこれを宣言しなければなりません。OrderLineへの関連は次のようにマッピングされます。
<many-to-one name="orderLine" class="OrderLine">
<!-- the "class" attribute is optional, as usual -->
<column name="lineId"/>
<column name="orderId"/>
<column name="customerId"/>
</many-to-one>
(Note that the <column> tag is an alternative to the column attribute everywhere.)
(<column>タグはどこであってもcolumn属性の代わりになります。)
A many-to-many association to OrderLine also uses the composite foreign key:
OrderLineへのmany-to-many関連も複合外部キーを使います。
<set name="undeliveredOrderLines">
<key column name="warehouseId"/>
<many-to-many class="OrderLine">
<column name="lineId"/>
<column name="orderId"/>
<column name="customerId"/>
</many-to-many>
</set>
The collection of OrderLines in Order would use:
OrderにあるOrderLineのコレクションは次のものを使用します。
<set name="orderLines" inverse="true">
<key>
<column name="orderId"/>
<column name="customerId"/>
</key>
<one-to-many class="OrderLine"/>
</set>
(The <one-to-many> element, as usual, declares no columns.)
(<one-to-many>属性は、例によってカラムを宣言しません)
If OrderLine itself owns a collection, it also has a composite foreign key.
OrderLine自身がコレクションを持っている場合、同時に複合外部キーも持っています。
<class name="OrderLine">
....
....
<list name="deliveryAttempts">
<key> <!-- a collection inherits the composite key type -->
<column name="lineId"/>
<column name="orderId"/>
<column name="customerId"/>
</key>
<list-index column="attemptId" base="1"/>
<composite-element class="DeliveryAttempt">
...
</composite-element>
</set>
</class>
8.5. Dynamic components(動的コンポーネント)
You may even map a property of type Map:
Map型のプロパティのマッピングも可能です。
<dynamic-component name="userAttributes">
<property name="foo" column="FOO" type="string"/>
<property name="bar" column="BAR" type="integer"/>
<many-to-one name="baz" class="Baz" column="BAZ_ID"/>
</dynamic-component>
The semantics of a <dynamic-component> mapping are identical to <component>. The advantage of this kind of mapping is the ability to determine the actual properties of the bean at deployment time, just by editing the mapping document. Runtime manipulation of the mapping document is also possible, using a DOM parser. Even better, you can access (and change) Hibernate's configuration-time metamodel via theConfiguration object.
<dynamic-component>マッピングのセマンティクスは<component>と同一のものです。この種のマッピングの利点は、マッピングドキュメントの編集により、配置時にbeanの属性を決定できる点です。また、DOMパーサを利用して、マッピングドキュメントのランタイム操作が可能です。さらに、Configurationオブジェクト経由でHibernateのコンフィグレーション時のメタモデルにアクセス(または変更)が可能です。
No comments:
Post a Comment