Friday, May 30, 2008

HIBERNATE - Relational Persistence for Idiomatic Java - 24

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(関連マッピング)
8. Component Mapping(コンポーネントのマッピング)
9. Inheritance Mapping(継承マッピング)
10. Working with objects(オブジェクトを扱う)
11. Transactions And Concurrency(トランザクションと並行性)
12. Interceptors and events(インターセプタとイベント)
13. Batch processing(バッチ処理)
14. HQL: The Hibernate Query Language(HQLHibernateクエリ言語)
15. Criteria Queries(Criteriaクエリ)
16. Native SQL(ネイティブSQL)
17. Filtering data(フィルタリングデータ)
18. XML Mapping(XMLマッピング)
19. Improving performance(パフォーマンスの改善)
20. Toolset Guide(ツールセットガイド)
21. Example: Parent/Child(例:親/)
22. Example: Weblog Application(例:Weblogアプリケーション)
23. Example: Various Mappings(例:いろいろなマッピング)
24. Best Practices(ベストプラクティス)


Chapter 24. Best Practices(24章:ベストプラクティス)
Write fine-grained classes and map them using <component>.(クラスは細かい粒度で書き <component> でマッピングしましょう。)
Use an Address class to encapsulate streetsuburbstatepostcode. This encourages code reuse and simplifies refactoring.
street(通り), suburb(都市), state(州), postcode (郵便番号)をカプセル化するAddress(住所)クラスを使いましょう。そうすればコードが再利用しやすくなり、リファクタリングも簡単になります。
Declare identifier properties on persistent classes.( 永続クラスには識別子プロパティを定義しましょう。)
Hibernate makes identifier properties optional. There are all sorts of reasons why you should use them. We recommend that identifiers be 'synthetic' (generated, with no business meaning).
Hibernateでは識別子プロパティはオプションですが、使用すべき理由がたくさんあります。識別子は「人工的」(生成された、業務的な意味を持たない)なものにすることをおすすめします。
Identify natural keys.( 自然キーを見つけましょう。)
Identify natural keys for all entities, and map them using <natural-id>. Implementequals() and hashCode() to compare the properties that make up the natural key.
すべてのエンティティに対して自然キーを見つけて、<natural-id> でマッピングしましょう。自然キーを構成するプロパティを比較するために、equals()  hashCode() を実装しましょう。
Place each class mapping in its own file.( クラスのマッピングはそれぞれのクラス専用のファイルに書きましょう。)
Don't use a single monolithic mapping document. Map com.eg.Foo in the filecom/eg/Foo.hbm.xml. This makes particularly good sense in a team environment.
単一の巨大なマッピングドキュメントを使用しないでください。com.eg.Foo クラスならcom/eg/Foo.hbm.xml ファイルにマッピングしましょう。このことは、特にチームでの開発に意味があります。
Load mappings as resources.( リソースとしてマッピングをロードしましょう。)
Deploy the mappings along with the classes they map.
マッピングを、それらがマッピングするするクラスと一緒に配置しましょう。
Consider externalising query strings.( クエリ文字列を外部に置くことを考えましょう)
This is a good practice if your queries call non-ANSI-standard SQL functions. Externalising the query strings to mapping files will make the application more portable.
クエリがANSI標準でないSQL関数を呼んでいるなら、これはよいプラクティスです。クエリ文字列をマッピングファイルへ外出しすればアプリケーションがポータブルになります。
Use bind variables.( バインド変数を使いましょう。)
As in JDBC, always replace non-constant values by "?". Never use string manipulation to bind a non-constant value in a query! Even better, consider using named parameters in queries.
JDBCの場合と同じように、定数でない値は必ず"?"で置き換えましょう。定数でない値をバインドするために、クエリで文字列操作を使ってはいけません。名前付きのパラメータを使うようにするとさらに良いです。
Don't manage your own JDBC connections.( JDBCコネクションを管理してはいけません。)
Hibernate lets the application manage JDBC connections. This approach should be considered a last-resort. If you can't use the built-in connections providers, consider providing your own implementation of org.hibernate.connection.ConnectionProvider.
HibernateではアプリケーションがJDBCコネクションを管理することが許されています。しかしこれは最終手段だと思ってください。組み込みのコネクションプロバイダを使うことができなければ、org.hibernate.connection.ConnectionProvider を実装することを考えてください。
Consider using a custom type.( カスタム型の使用を考えましょう。)
Suppose you have a Java type, say from some library, that needs to be persisted but doesn't provide the accessors needed to map it as a component. You should consider implementing org.hibernate.UserType. This approach frees the application code from implementing transformations to / from a Hibernate type.
あるライブラリから持ってきたJava型を永続化する必要があるとしましょう。しかしその型には、コンポーネントとしてマッピングするために必要なアクセサがないとします。このような場合は org.hibernate.UserType の実装を考えるべきです。そうすればHibernate型との実装変換を心配せずにアプリケーションのコードを扱えます。
Use hand-coded JDBC in bottlenecks.( ボトルネックを解消するにはJDBCをハンドコードしましょう。)
In performance-critical areas of the system, some kinds of operations might benefit from direct JDBC. But please, wait until you know something is a bottleneck. And don't assume that direct JDBC is necessarily faster. If you need to use direct JDBC, it might be worth opening a Hibernate Session and using that JDBC connection. That way you can still use the same transaction strategy and underlying connection provider.
システムのパフォーマンスクリティカルな領域では、ある種の操作にJDBCを直接使うと良いかもしれません。しかし何がボトルネックになっているか はっきりする までは待ってください。またJDBCを直接使うからといって、必ずしも速くなるとは限らないことも理解してください。JDBCを直接使う必要があれば、Hibernate Session をオープンして、JDBCコネクションを使うと良いかもしれません。依然として同じトランザクション戦略とコネクションプロバイダが使えるからです。
Understand Session flushing.( Session のフラッシュを理解しましょう。)
From time to time the Session synchronizes its persistent state with the database. Performance will be affected if this process occurs too often. You may sometimes minimize unnecessary flushing by disabling automatic flushing or even by changing the order of queries and other operations within a particular transaction.
Sessionが永続状態をデータベースと同期させることがときどきあります。しかしこれがあまりに頻繁に起こるようだと、パフォーマンスに影響が出てきます。自動フラッシュを無効にしたり、特定のトランザクションのクエリや操作の順番を変更することで、不必要なフラッシュを最小限にできます。
In a three tiered architecture, consider using detached objects.( 3層アーキテクチャでは分離オブジェクトの使用を考えましょう。)
When using a servlet / session bean architecture, you could pass persistent objects loaded in the session bean to and from the servlet / JSP layer. Use a new session to service each request. Use Session.merge() or Session.saveOrUpdate() to synchronize objects with the database.
サーブレット / セッションビーンアーキテクチャを使うとき、サーブレット層 / JSP層間でセッションビーンでロードした永続オブジェクトをやり取りできます。その際リクエストごとに新しいSessionを使ってください。また Session.merge() Session.saveOrUpdate() を使って、オブジェクトとデータベースを同期させてください。
In a two tiered architecture, consider using long persistence contexts.( 2層アーキテクチャでは長い永続コンテキストの使用を考えましょう。)
Database Transactions have to be as short as possible for best scalability. However, it is often neccessary to implement long running application transactions, a single unit-of-work from the point of view of a user. An application transaction might span several client request/response cycles. It is common to use detached objects to implement application transactions. An alternative, extremely appropriate in two tiered architecture, is to maintain a single open persistence contact (session) for the whole lifecycle of the application transaction and simply disconnect from the JDBC connection at the end of each request and reconnect at the beginning of the subsequent request. Never share a single session across more than one application transaction, or you will be working with stale data.
最高のスケーラビリティを得るには、データベーストランザクションをできるだけ短くしなければなりません。しかし長い間実行する アプリケーショントランザクション の実装が必要なことはしばしばです。これはユーザの視点からは1個の作業単位(unit of work)になります。アプリケーショントランザクションはいくつかのクライアントのリクエスト/レスポンスサイクルにまたがります。アプリケーショントランザクションの実装に分離オブジェクトを使うのは一般的です。そうでなければ、2層アーキテクチャの場合は特に適切なことですが、アプリケーショントランザクションのライフサイクル全体に対して単一のオープンな永続化コンテキスト(セッション)を維持してください。そして単純にリクエストの最後にJDBCコネクションから切断し、次のリクエストの最初に再接続します。決して複数のアプリケーショントランザクションユースケースに渡って1個のSessionを使い回さないでください。そうでなければ、古いデータで作業することになります。
Don't treat exceptions as recoverable.( 例外を復帰可能なものとして扱ってはいけません。)
This is more of a necessary practice than a "best" practice. When an exception occurs, roll back the Transaction and close the Session. If you don't, Hibernate can't guarantee that in-memory state accurately represents persistent state. As a special case of this, do not use Session.load() to determine if an instance with the given identifier exists on the database; use Session.get() or a query instead.
これは「ベスト」プラクティス以上の、必須のプラクティスです。例外が発生したときはTransaction をロールバックして、Session をクローズしてください。そうしないとHibernateはメモリの状態が永続状態を正確に表現していることを保証できません。この特別な場合として、与えられた識別子を持つインスタンスがデータベースに存在するかどうかを判定するために、Session.load() を使うことはやめてください。その代わりにSession.get() かクエリを使ってください。
Prefer lazy fetching for associations.( 関連にはなるべく遅延フェッチを使いましょう。)
Use eager fetching sparingly. Use proxies and lazy collections for most associations to classes that are not likely to be completely held in the second-level cache. For associations to cached classes, where there is an a extremely high probability of a cache hit, explicitly disable eager fetching using lazy="false". When an join fetching is appropriate to a particular use case, use a query with a left join fetch.
即時フェッチは控えめにしましょう。二次キャッシュには完全に保持されないようなクラスの関連には、プロキシと遅延コレクションを使ってください。キャッシュされるクラスの関連、つまりキャッシュがヒットする可能性が非常に高い関連は、lazy="false" で積極的なフェッチを明示的に無効にしてください。結合フェッチが適切な特定のユースケースには、クエリで left join fetch を使ってください。
Use the open session in view pattern, or a disciplined assembly phase to avoid problems with unfetched data. (フェッチされていないデータに関わる問題を避けるために、ビューの中でオープンセッションを使う(open session in view) パターンか、統制された 組み立てフェーズ(assembly phase) を使いましょう。)
Hibernate frees the developer from writing tedious Data Transfer Objects (DTO). In a traditional EJB architecture, DTOs serve dual purposes: first, they work around the problem that entity beans are not serializable; second, they implicitly define an assembly phase where all data to be used by the view is fetched and marshalled into the DTOs before returning control to the presentation tier. Hibernate eliminates the first purpose. However, you will still need an assembly phase (think of your business methods as having a strict contract with the presentation tier about what data is available in the detached objects) unless you are prepared to hold the persistence context (the session) open across the view rendering process. This is not a limitation of Hibernate! It is a fundamental requirement of safe transactional data access.
Hibernate Data Transfer Objects (DTO)を書く退屈な作業から開発者を解放します。伝統的なEJBアーキテクチャではDTOは二つ目的があります:1つ目は、エンティティビーンがシリアライズされない問題への対策です。2つ目は、プレゼンテーション層に制御が戻る前に、ビューに使われるすべてのデータがフェッチされて、DTOに復元されるような組み立てフェーズを暗黙的に定義します。Hibernateでは1つ目の目的が不要になります。しかしビューのレンダリング処理の間、永続コンテキスト(セッション)をオープンにしたままにしなければ、組み立てフェーズはまだ必要です(分離オブジェクトの中のどのデータが利用可能かについて、プレゼンテーション層と厳密な取り決めをしているビジネスメソッドを考えてみてください)。これはHibernate側の問題ではありません。トランザクション内で安全にデータアクセスするための基本的な要件です。
Consider abstracting your business logic from Hibernate.( Hibernateからビジネスロジックを抽象化することを考えましょう。)
Hide (Hibernate) data-access code behind an interface. Combine the DAO and Thread Local Session patterns. You can even have some classes persisted by handcoded JDBC, associated to Hibernate via a UserType. (This advice is intended for "sufficiently large" applications; it is not appropriate for an application with five tables!)
インターフェイスで(Hibernateの)データアクセスコードを隠蔽しましょう。DAO Thread Local Session パターンを組み合わせましょう。UserType Hibernateに関連付けると、ハンドコードしたJDBCで永続化するクラスを持つこともできます。(このアドバイスは「十分大きな」アプリケーションに対してのものです。テーブルが5個しかないようなアプリケーションには当てはまりません。)
Don't use exotic association mappings.( 珍しい関連マッピングは使わないようにしましょう。)
Good usecases for a real many-to-many associations are rare. Most of the time you need additional information stored in the "link table". In this case, it is much better to use two one-to-many associations to an intermediate link class. In fact, we think that most associations are one-to-many and many-to-one, you should be careful when using any other association style and ask yourself if it is really neccessary.
よいユースケースに本当の多対多関連があることは稀(まれ)です。ほとんどの場合「リンクテーブル」の付加的な情報が必要になります。この場合、リンククラスに2つの1対多関連を使う方がずっと良いです。実際ほとんどの場合関連は1対多と多対1なので、他のスタイルの関連を使うときは本当に必要かどうかを考えてみてください。
Prefer bidirectional associations.( なるべく双方向関連にしましょう。)
Unidirectional associations are more difficult to query. In a large application, almost all associations must be navigable in both directions in queries.
単方向関連は双方向に比べて検索が難しくなります。大きなアプリケーションでは、ほとんどすべての関連が双方向にナビゲーションできなければなりません。

Thursday, May 29, 2008

HIBERNATE - Relational Persistence for Idiomatic Java - 23

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(関連マッピング)
8. Component Mapping(コンポーネントマッピング)
9. Inheritance Mapping(継承マッピング)
10. Working with objects(オブジェクトを扱う)
11. Transactions And Concurrency(トランザクションと並行性)
12. Interceptors and events(インターセプタとイベント)
13. Batch processing(バッチ処理)
14. HQL: The Hibernate Query Language(HQLHibernateクエリ言語)
15. Criteria Queries(Criteriaクエリ)
16. Native SQL(ネイティブSQL)
17. Filtering data(データのフィルタリング)
18. XML Mapping(XMLマッピング)
19. Improving performance(パフォーマンスの改善)
20. Toolset Guide(ツールセットガイド)
21. Example: Parent/Child(例:親/)
22. Example: Weblog Application(例:Weblogアプリケーション)
23. Example: Various Mappings(例:いろいろなマッピング)
23.1. Employer/Employee(雇用者/従業員)
23.2. Author/Work(作者/作品)
23.3. Customer/Order/Product(顧客/注文/製品)
23.4. Miscellaneous example mappings(種々雑多なマッピング例)
23.4.1. "Typed" one-to-one association(Typed」一対一関連)
23.4.2. Composite key example(複合キーの例)
23.4.3. Many-to-many with shared composite key attribute(複合キー属性を共有する多対多)
23.4.4. Content based discrimination(discriminationに基づく内容)
23.4.5. Associations on alternate keys(代替キーの関連)


Chapter 23. Example: Various Mappings(23章:様々なマッピング)
This chapters shows off some more complex association mappings.
この章では、より複雑な関連のマッピングをいくつか紹介します。
23.1. Employer/Employee(雇用者/従業員)
The following model of the relationship between Employer and Employee uses an actual entity class (Employment) to represent the association. This is done because there might be more than one period of employment for the same two parties. Components are used to model monetary values and employee names.
Employer  Employee の関係を表す以下のモデルは、関連の表現に実際のエンティティクラス( Employment )を使います。なぜなら、同じ2つのパーティに複数の期間雇用されるということがありえるからです。お金の値と従業員の名前をモデル化するためにコンポーネントを使っています。

Heres a possible mapping document:
マッピングドキュメントの一例です:
<hibernate-mapping>
        
    <class name="Employer" table="employers">
        <id name="id">
            <generator class="sequence">
                <param name="sequence">employer_id_seq</param>
            </generator>
        </id>
        <property name="name"/>
    </class>

    <class name="Employment" table="employment_periods">

        <id name="id">
            <generator class="sequence">
                <param name="sequence">employment_id_seq</param>
            </generator>
        </id>
        <property name="startDate" column="start_date"/>
        <property name="endDate" column="end_date"/>

        <component name="hourlyRate" class="MonetaryAmount">
            <property name="amount">
                <column name="hourly_rate" sql-type="NUMERIC(12, 2)"/>
            </property>
            <property name="currency" length="12"/>
        </component>

        <many-to-one name="employer" column="employer_id" not-null="true"/>
        <many-to-one name="employee" column="employee_id" not-null="true"/>

    </class>

    <class name="Employee" table="employees">
        <id name="id">
            <generator class="sequence">
                <param name="sequence">employee_id_seq</param>
            </generator>
        </id>
        <property name="taxfileNumber"/>
        <component name="name" class="Name">
            <property name="firstName"/>
            <property name="initial"/>
            <property name="lastName"/>
        </component>
    </class>

</hibernate-mapping>
And heres the table schema generated by SchemaExport.
SchemaExportで生成したテーブルスキーマです。
create table employers (
    id BIGINT not null, 
    name VARCHAR(255), 
    primary key (id)
)

create table employment_periods (
    id BIGINT not null,
    hourly_rate NUMERIC(12, 2),
    currency VARCHAR(12), 
    employee_id BIGINT not null, 
    employer_id BIGINT not null, 
    end_date TIMESTAMP, 
    start_date TIMESTAMP, 
    primary key (id)
)

create table employees (
    id BIGINT not null, 
    firstName VARCHAR(255), 
    initial CHAR(1), 
    lastName VARCHAR(255), 
    taxfileNumber VARCHAR(255), 
    primary key (id)
)

alter table employment_periods 
    add constraint employment_periodsFK0 foreign key (employer_id) references employers
alter table employment_periods 
    add constraint employment_periodsFK1 foreign key (employee_id) references employees
create sequence employee_id_seq
create sequence employment_id_seq
create sequence employer_id_seq
23.2. Author/Work(作者/作品)
Consider the following model of the relationships between WorkAuthor and Person. We represent the relationship between Work and Author as a many-to-many association. We choose to represent the relationship between Author and Person as one-to-one association. Another possibility would be to have Author extend Person.
Work , Author そして Person の関係を表す以下のモデルを考えてみてください。Work Author の関係を多対多関連で表しています。Author  Person の関係は一対一関連として表しています。他には Author  Person を拡張するという方法もあります。

The following mapping document correctly represents these relationships:
以下のマッピングドキュメントはこのような関係を正確に表現しています。
<hibernate-mapping>

    <class name="Work" table="works" discriminator-value="W">

        <id name="id" column="id">
            <generator class="native"/>
        </id>
        <discriminator column="type" type="character"/>

        <property name="title"/>
        <set name="authors" table="author_work">
            <key column name="work_id"/>
            <many-to-many class="Author" column name="author_id"/>
        </set>

        <subclass name="Book" discriminator-value="B">
            <property name="text"/>
        </subclass>

        <subclass name="Song" discriminator-value="S">
            <property name="tempo"/>
            <property name="genre"/>
        </subclass>

    </class>

    <class name="Author" table="authors">

        <id name="id" column="id">
            <!-- The Author must have the same identifier as the Person -->
            <generator class="assigned"/> 
        </id>

        <property name="alias"/>
        <one-to-one name="person" constrained="true"/>

        <set name="works" table="author_work" inverse="true">
            <key column="author_id"/>
            <many-to-many class="Work" column="work_id"/>
        </set>

    </class>

    <class name="Person" table="persons">
        <id name="id" column="id">
            <generator class="native"/>
        </id>
        <property name="name"/>
    </class>

</hibernate-mapping>
There are four tables in this mapping. worksauthors and persons hold work, author and person data respectively. author_work is an association table linking authors to works. Heres the table schema, as generated by SchemaExport.
このマッピングには4つのテーブルがあります。works , authors , persons はそれぞれ、仕事、作者、人のデータを保持します。author_work は作者と作品をリンクする関連テーブルです。以下は SchemaExport で生成したテーブルスキーマです。
create table works (
    id BIGINT not null generated by default as identity, 
    tempo FLOAT, 
    genre VARCHAR(255), 
    text INTEGER, 
    title VARCHAR(255), 
    type CHAR(1) not null, 
    primary key (id)
)

create table author_work (
    author_id BIGINT not null, 
    work_id BIGINT not null, 
    primary key (work_id, author_id)
)

create table authors (
    id BIGINT not null generated by default as identity, 
    alias VARCHAR(255), 
    primary key (id)
)

create table persons (
    id BIGINT not null generated by default as identity, 
    name VARCHAR(255), 
    primary key (id)
)

alter table authors 
    add constraint authorsFK0 foreign key (id) references persons
alter table author_work 
    add constraint author_workFK0 foreign key (author_id) references authors
alter table author_work
    add constraint author_workFK1 foreign key (work_id) references works
23.3. Customer/Order/Product(顧客/注文/製品)
Now consider a model of the relationships between CustomerOrder and LineItem andProduct. There is a one-to-many association between Customer and Order, but how should we represent Order / LineItem / Product? I've chosen to map LineItem as an association class representing the many-to-many association between Order and Product. In Hibernate, this is called a composite element.
さて、 Customer , Order , LineItem Product の関係を表すモデルを考えてみましょう。Customer  Order は一対多の関連ですが、Order / LineItem / Product はどのように表現するべきでしょうか?LineItem を、Order  Product の多対多関連を表現する関連クラスとしてマッピングしました。Hibernateではこれをコンポジット要素と呼びます。

The mapping document:
マッピングドキュメント:
<hibernate-mapping>

    <class name="Customer" table="customers">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name"/>
        <set name="orders" inverse="true">
            <key column="customer_id"/>
            <one-to-many class="Order"/>
        </set>
    </class>

    <class name="Order" table="orders">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="date"/>
        <many-to-one name="customer" column="customer_id"/>
        <list name="lineItems" table="line_items">
            <key column="order_id"/>
            <list-index column="line_number"/>
            <composite-element class="LineItem">
                <property name="quantity"/>
                <many-to-one name="product" column="product_id"/>
            </composite-element>
        </list>
    </class>

    <class name="Product" table="products">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="serialNumber"/>
    </class>

</hibernate-mapping>
customersordersline_items and products hold customer, order, order line item and product data respectively. line_items also acts as an association table linking orders with products.
customers , orders , line_items , products はそれぞれ、顧客、注文、注文明細、製品のデータを保持します。line_items は注文と製品をリンクする関連テーブルとしても働きます。
create table customers (
    id BIGINT not null generated by default as identity, 
    name VARCHAR(255), 
    primary key (id)
)

create table orders (
    id BIGINT not null generated by default as identity, 
    customer_id BIGINT, 
    date TIMESTAMP, 
    primary key (id)
)

create table line_items (
    line_number INTEGER not null, 
    order_id BIGINT not null, 
    product_id BIGINT, 
    quantity INTEGER, 
    primary key (order_id, line_number)
)

create table products (
    id BIGINT not null generated by default as identity, 
    serialNumber VARCHAR(255), 
    primary key (id)
)

alter table orders 
    add constraint ordersFK0 foreign key (customer_id) references customers
alter table line_items
    add constraint line_itemsFK0 foreign key (product_id) references products
alter table line_items
    add constraint line_itemsFK1 foreign key (order_id) references orders
23.4. Miscellaneous example mappings(種々雑多なマッピング例)
These examples are all taken from the Hibernate test suite. You will find many other useful example mappings there. Look in the test folder of the Hibernate distribution.
ここにある例はすべてHibernateのテストスイートから取りました。そこには、他にもたくさんのマッピングの例があります。Hibernateディストリビューションの test フォルダを見てください。
TODO: put words around this stuff
TODO: ここに文章を埋める
23.4.1. "Typed" one-to-one association(Typed」一対一関連)
<class name="Person">
    <id name="name"/>
    <one-to-one name="address" 
            cascade="all">
        <formula>name</formula>
        <formula>'HOME'</formula>
    </one-to-one>
    <one-to-one name="mailingAddress" 
            cascade="all">
        <formula>name</formula>
        <formula>'MAILING'</formula>
    </one-to-one>
</class>

<class name="Address" batch-size="2" 
        check="addressType in ('MAILING', 'HOME', 'BUSINESS')">
    <composite-id>
        <key-many-to-one name="person" 
                column="personName"/>
        <key-property name="type" 
                column="addressType"/>
    </composite-id>
    <property name="street" type="text"/>
    <property name="state"/>
    <property name="zip"/>
</class>
23.4.2. Composite key example(複合キーの例)
<class name="Customer">

    <id name="customerId"
        length="10">
        <generator class="assigned"/>
    </id>

    <property name="name" not-null="true" length="100"/>
    <property name="address" not-null="true" length="200"/>

    <list name="orders"
            inverse="true"
            cascade="save-update">
        <key column="customerId"/>
        <index column="orderNumber"/>
        <one-to-many class="Order"/>
    </list>

</class>

<class name="Order" table="CustomerOrder" lazy="true">
    <synchronize table="LineItem"/>
    <synchronize table="Product"/>
    
    <composite-id name="id" 
            class="Order$Id">
        <key-property name="customerId" length="10"/>
        <key-property name="orderNumber"/>
    </composite-id>
    
    <property name="orderDate" 
            type="calendar_date"
            not-null="true"/>
    
    <property name="total">
        <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 )
        </formula>
    </property>
    
    <many-to-one name="customer"
            column="customerId"
            insert="false"
            update="false" 
            not-null="true"/>
        
    <bag name="lineItems"
            fetch="join" 
            inverse="true"
            cascade="save-update">
        <key>
            <column name="customerId"/>
            <column name="orderNumber"/>
        </key>
        <one-to-many class="LineItem"/>
    </bag>
    
</class>
    
<class name="LineItem">
    
    <composite-id name="id" 
            class="LineItem$Id">
        <key-property name="customerId" length="10"/>
        <key-property name="orderNumber"/>
        <key-property name="productId" length="10"/>
    </composite-id>
    
    <property name="quantity"/>
    
    <many-to-one name="order"
            insert="false"
            update="false" 
            not-null="true">
        <column name="customerId"/>
        <column name="orderNumber"/>
    </many-to-one>
    
    <many-to-one name="product"
            insert="false"
            update="false" 
            not-null="true"
            column="productId"/>
        
</class>

<class name="Product">
    <synchronize table="LineItem"/>

    <id name="productId"
        length="10">
        <generator class="assigned"/>
    </id>
    
    <property name="description" 
        not-null="true" 
        length="200"/>
    <property name="price" length="3"/>
    <property name="numberAvailable"/>
    
    <property name="numberOrdered">
        <formula>
            ( select sum(li.quantity) 
            from LineItem li 
            where li.productId = productId )
        </formula>
    </property>
    
</class>
23.4.3. Many-to-many with shared composite key attribute(複合キー属性を共有する多対多)
<class name="User" table="`User`">
    <composite-id>
        <key-property name="name"/>
        <key-property name="org"/>
    </composite-id>
    <set name="groups" table="UserGroup">
        <key>
            <column name="userName"/>
            <column name="org"/>
        </key>
        <many-to-many class="Group">
            <column name="groupName"/>
            <formula>org</formula>
        </many-to-many>
    </set>
</class>
    
<class name="Group" table="`Group`">
    <composite-id>
        <key-property name="name"/>
        <key-property name="org"/>
    </composite-id>
    <property name="description"/>
    <set name="users" table="UserGroup" inverse="true">
        <key>
            <column name="groupName"/>
            <column name="org"/>
        </key>
        <many-to-many class="User">
            <column name="userName"/>
            <formula>org</formula>
        </many-to-many>
    </set>
</class>
23.4.4. Content based discrimination(discriminationに基づく内容)
<class name="Person"
    discriminator-value="P">
    
    <id name="id" 
        column="person_id" 
        unsaved-value="0">
        <generator class="native"/>
    </id>
    
            
    <discriminator 
        type="character">
        <formula>
            case 
                when title is not null then 'E' 
                when salesperson is not null then 'C' 
                else 'P' 
            end
        </formula>
    </discriminator>

    <property name="name" 
        not-null="true"
        length="80"/>
        
    <property name="sex" 
        not-null="true"
        update="false"/>
    
    <component name="address">
        <property name="address"/>
        <property name="zip"/>
        <property name="country"/>
    </component>
    
    <subclass name="Employee" 
        discriminator-value="E">
            <property name="title"
                length="20"/>
            <property name="salary"/>
            <many-to-one name="manager"/>
    </subclass>
    
    <subclass name="Customer" 
        discriminator-value="C">
            <property name="comments"/>
            <many-to-one name="salesperson"/>
    </subclass>
    
</class>
23.4.5. Associations on alternate keys(代替キーの関連)
<class name="Person">
    
    <id name="id">
        <generator class="hilo"/>
    </id>
    
    <property name="name" length="100"/>
    
    <one-to-one name="address" 
        property-ref="person"
        cascade="all"
        fetch="join"/>
    
    <set name="accounts" 
        inverse="true">
        <key column="userId"
            property-ref="userId"/>
        <one-to-many class="Account"/>
    </set>
    
    <property name="userId" length="8"/>

</class>

<class name="Address">

    <id name="id">
        <generator class="hilo"/>
    </id>

    <property name="address" length="300"/>
    <property name="zip" length="5"/>
    <property name="country" length="25"/>
    <many-to-one name="person" unique="true" not-null="true"/>

</class>

<class name="Account">
    <id name="accountId" length="32">
        <generator class="uuid"/>
    </id>
    
    <many-to-one name="user"
        column="userId"
        property-ref="userId"/>
    
    <property name="type" not-null="true"/>
    
</class>