Hibernate.org Community Documentation

# HIBERNATE - Relational Persistence for Idiomatic Java

## Hibernate Reference Documentation

： King Gavin [FAMILY Given], Bauer Christian [FAMILY Given], Andersen Max [FAMILY Given], Bernard Emmanuel [FAMILY Given], Ebersole Steve [FAMILY Given], 、 Ferentschik Hardy [FAMILY Given]
and thanks to Cobb James [FAMILY Given] (Graphic Design) 、 Weaver Cheyenne [FAMILY Given] (Graphic Design)

3.6.10.Final

製作著作 © 2004 Red Hat, Inc.

Legal Notice

February 8, 2012

## 前書き

Working with both Object-Oriented software and Relational Databases can be cumbersome and time consuming. Development costs are significantly higher due to a paradigm mismatch between how data is represented in objects versus relational databases. Hibernate is an Object/Relational Mapping solution for Java environments. The term Object/Relational Mapping refers to the technique of mapping data from an object model representation to a relational data model representation (and visa versa). See http://en.wikipedia.org/wiki/Object-relational_mapping for a good high-level discussion.

## 注意

While having a strong background in SQL is not required to use Hibernate, having a basic understanding of the concepts can greatly help you understand Hibernate more fully and quickly. Probably the single best background is an understanding of data modeling principles. You might want to consider these resources as a good starting point:

- http://www.agiledata.org/essays/dataModeling101.html

- http://en.wikipedia.org/wiki/Data_modeling

Hibernate not only takes care of the mapping from Java classes to database tables (and from Java data types to SQL data types), but also provides data query and retrieval facilities. It can significantly reduce development time otherwise spent with manual data handling in SQL and JDBC. Hibernate’s design goal is to relieve the developer from 95% of common data persistence-related programming tasks by eliminating the need for manual, hand-crafted data processing using SQL and JDBC. However, unlike many other persistence solutions, Hibernate does not hide the power of SQL from you and guarantees that your investment in relational technology and knowledge is as valid as always.

Hibernate may not be the best solution for data-centric applications that only use stored-procedures to implement the business logic in the database, it is most useful with object-oriented domain models and business logic in the Java-based middle-tier. However, Hibernate can certainly help you to remove or encapsulate vendor-specific SQL code and will help with the common task of result set translation from a tabular representation to a graph of objects.

Hibernate 及びオブジェクト/リレーショナルマッピング、 あるいは Java が不慣れな方は、 次の手順を行ってください。

1. Read 1章Tutorial for a tutorial with step-by-step instructions. The source code for the tutorial is included in the distribution in the `doc/reference/tutorial/` directory.

2. Read 2章アーキテクチャ to understand the environments where Hibernate can be used.

3. Hibernate ディストリビューション内の `eg/` ディレクトリ内を見てください。 シンプルなスタンドアローンのアプリケーションが含まれています。 ご使用の JDBC ドライバを `lib/` ディレクトリにコピーしてから使用するデータベースに対して正しい値を指定するよう `etc/hibernate.properties` を編集します。 ディストリビューションディレクトリ内のコマンドプロンプトから、 `ant eg` (Ant を使用)と入力するか、 Windows 環境の場合は `build eg` と入力します。

4. Use this reference documentation as your primary source of information. Consider reading [JPwH] if you need more help with application design, or if you prefer a step-by-step tutorial. Also visit http://caveatemptor.hibernate.org and download the example application from [JPwH].

5. よくある質問とその答え (FAQ) は Hibernate ウェブサイトでご覧ください。

6. Links to third party demos, examples, and tutorials are maintained on the Hibernate website.

7. Hibernate ウェブサイト上の Community Area はデザインのパターンやさまざまな統合ソリューション (Tomcat、 JBoss AS、 Struts、 EJB など)を検索する上で興味深いリソースになります。

There are a number of ways to become involved in the Hibernate community, including

- Trying stuff out and reporting bugs. See http://hibernate.org/issuetracker.html details.

- Trying your hand at fixing some bugs or implementing enhancements. Again, see http://hibernate.org/issuetracker.html details.

- http://hibernate.org/community.html list a few ways to engage in the community.

  - There are forums for users to ask questions and receive help from the community.

  - There are also IRC channels for both user and developer discussions.

- Helping improve or translate this documentation. Contact us on the developer mailing list if you have interest.

- Evangelizing Hibernate within your organization.

## 第1章 Tutorial

Intended for new users, this chapter provides an step-by-step introduction to Hibernate, starting with a simple application using an in-memory database. The tutorial is based on an earlier tutorial developed by Michael Gloegl. All code is contained in the `tutorials/web` directory of the project source.

## 重要項目

This tutorial expects the user have knowledge of both Java and SQL. If you have a limited knowledge of JAVA or SQL, it is advised that you start with a good introduction to that technology prior to attempting to learn Hibernate.

## 注意

The distribution contains another example application under the `tutorial/eg` project source directory.

## 1.1. パート1 - 初めての Hibernate アプリケーション

仮に小さなデータベースアプリケーションが必要だとしましょう。そのアプリケーションには出席したいイベントと、そのイベントのホストについての情報を格納するものとします。

## 注意

Although you can use whatever database you feel comfortable using, we will use HSQLDB (an in-memory, Java database) to avoid describing installation/setup of any particular database servers.

### 1.1.1. Setup

The first thing we need to do is to set up the development environment. We will be using the "standard layout" advocated by alot of build tools such as Maven. Maven, in particular, has a good resource describing this layout. As this tutorial is to be a web application, we will be creating and making use of `src/main/java`, `src/main/resources` and `src/main/webapp` directories.

We will be using Maven in this tutorial, taking advantage of its transitive dependency management capabilities as well as the ability of many IDEs to automatically set up a project for us based on the maven descriptor.

    <project xmlns="http://maven.apache.org/POM/4.0.0"

             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

        <modelVersion>4.0.0</modelVersion>

        <groupId>org.hibernate.tutorials</groupId>

        <artifactId>hibernate-tutorial</artifactId>

        <version>1.0.0-SNAPSHOT</version>

        <name>First Hibernate Tutorial</name>

        <build>

             <!-- we dont want the version to be part of the generated war file name -->

             <finalName>${artifactId}</finalName>

        </build>

        <dependencies>

            <dependency>

                <groupId>org.hibernate</groupId>

                <artifactId>hibernate-core</artifactId>

            </dependency>

            <!-- Because this is a web app, we also have a dependency on the servlet api. -->

            <dependency>

                <groupId>javax.servlet</groupId>

                <artifactId>servlet-api</artifactId>

            </dependency>

            <!-- Hibernate uses slf4j for logging, for our purposes here use the simple backend -->

            <dependency>

                <groupId>org.slf4j</groupId>

                <artifactId>slf4j-simple</artifactId>

            </dependency>

            <!-- Hibernate gives you a choice of bytecode providers between cglib and javassist -->

            <dependency>

                <groupId>javassist</groupId>

                <artifactId>javassist</artifactId>

            </dependency>

        </dependencies>

    </project>

## ティップ

It is not a requirement to use Maven. If you wish to use something else to build this tutorial (such as Ant), the layout will remain the same. The only change is that you will need to manually account for all the needed dependencies. If you use something like Ivy providing transitive dependency management you would still use the dependencies mentioned below. Otherwise, you'd need to grab all dependencies, both explicit and transitive, and add them to the project's classpath. If working from the Hibernate distribution bundle, this would mean `hibernate3.jar`, all artifacts in the `lib/required` directory and all files from either the `lib/bytecode/cglib` or `lib/bytecode/javassist` directory; additionally you will need both the servlet-api jar and one of the slf4j logging backends.

Save this file as `pom.xml` in the project root directory.

### 1.1.2. 最初のクラス

次にデータベースに格納するイベントを表すクラスを作成します。

    package org.hibernate.tutorial.domain;

    import java.util.Date;

    public class Event {

        private Long id;

        private String title;

        private Date date;

        public Event() {}

        public Long getId() {

            return id;

        }

        private void setId(Long id) {

            this.id = id;

        }

        public Date getDate() {

            return date;

        }

        public void setDate(Date date) {

            this.date = date;

        }

        public String getTitle() {

            return title;

        }

        public void setTitle(String title) {

            this.title = title;

        }

    }

This class uses standard JavaBean naming conventions for property getter and setter methods, as well as private visibility for the fields. Although this is the recommended design, it is not required. Hibernate can also access fields directly, the benefit of accessor methods is robustness for refactoring.

`id` プロパティは、ある特定のイベントに対するユニークな識別子の値を保持します。 Hibernate の完全な機能を使いたければ、すべての永続エンティティクラス （それほど重要ではない依存クラスというものもあります） にこのような識別子プロパティが必要になります。事実上ほとんどのアプリケーション （ 特に web アプリケーション） では、識別子でオブジェクトを区別する必要があるため、これは制限というよりも特徴であると考えるべきです。しかし通常オブジェクトの ID を操作するようなことはしません。そのためセッターメソッドは private にするべきです。 Hibernate だけがオブジェクトがセーブされたときに識別子へ値を代入します。 Hibernate が（public, private, protected）フィールドに直接アクセスできるのと同様に、 public, private, protected のアクセサメソッドにアクセスできるということがわかるでしょう。選択はあなたに任されているので、あなたのアプリケーションの設計に合わせることができます。

引数のないコンストラクタはすべての永続クラスに必須です。これは Hibernate が Java のリフレクションを使って、オブジェクトを作成しなければならないためです。コンストラクタを private にすることは可能ですが、実行時のプロキシ生成と、バイトコード操作なしの効率的なデータの抽出には、 package 可視性が必要です。

Save this file to the `src/main/java/org/hibernate/tutorial/domain` directory.

### 1.1.3. マッピングファイル

Hibernate は、どのように永続クラスのオブジェクトをロードし格納すればよいかを知る必要があります。ここで Hibernate マッピングファイルが登場します。マッピングファイルは、データベース内のどのテーブルにアクセスしなければならないか、そのテーブルのどのカラムを使うべきかを、 Hibernate に教えます。

マッピングファイルの基本的な構造はこのようになります：

    <?xml version="1.0"?>

    <!DOCTYPE hibernate-mapping PUBLIC

            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

    <hibernate-mapping package="org.hibernate.tutorial.domain">

    [...]

    </hibernate-mapping

    >

Hibernate DTD が非常に洗練されていることに注目してください。この DTD は、エディタや IDE での XML マッピング要素と属性のオートコンプリーション機能に利用できます。また DTD ファイルをテキストエディタで開けてみてください。というのも、すべての要素と属性を概観し、コメントやデフォルトの値を見るには一番簡単な方法だからです。 Hibernate は、 web から DTD ファイルをロードせずに、まずアプリケーションのクラスパスからこれを探し出そうとすることに注意してください。 DTD ファイルは Hibernate ディストリビューションの `src/` ディレクトリと同様、`hibernate3.jar` にも含まれています。

## 重要項目

以降の例ではコードを短くするために DTD 宣言を省略します。当然ですがこれはオプションではありません。

2つの `hibernate-mapping` タグの間に `class` 要素を含めてください。すべての永続エンティティクラス（念を押しますが、ファーストクラスのエンティティではない依存クラスというものが後ほど登場します）は SQL データベース内のテーブルへのこのようなマッピングを必要とします。

    <hibernate-mapping package="org.hibernate.tutorial.domain">

        <class name="Event" table="EVENTS">

        </class>

    </hibernate-mapping>

これまで私たちは、 `Event` クラスのオブジェクトを `EVENTS` テーブルに対して、どのように永続化したりロードしたりするのかを Hibernate に教えてきました。そして個々のインスタンスはテーブルの行として表現されます。それでは引き続きテーブルの主キーに対するユニークな識別子プロパティをマッピングしていきます。さらに、この識別子の扱いに気を使いたくなかったのと同様に、代理の主キーカラムに対する Hibernate の識別子生成戦略を設定します。

    <hibernate-mapping package="org.hibernate.tutorial.domain">

        <class name="Event" table="EVENTS">

            <id name="id" column="EVENT_ID">

                <generator class="native"/>

            </id>

        </class>

    </hibernate-mapping>

The `id` element is the declaration of the identifier property. The `name="id"` mapping attribute declares the name of the JavaBean property and tells Hibernate to use the `getId()` and `setId()` methods to access the property. The column attribute tells Hibernate which column of the `EVENTS` table holds the primary key value.

The nested `generator` element specifies the identifier generation strategy (aka how are identifier values generated?). In this case we choose `native`, which offers a level of portability depending on the configured database dialect. Hibernate supports database generated, globally unique, as well as application assigned, identifiers. Identifier value generation is also one of Hibernate's many extension points and you can plugin in your own strategy.

## ティップ

`native` is no longer consider the best strategy in terms of portability. for further discussion, see 「Identifier generation」

最後にクラスの永続プロパティの宣言をマッピングファイルに含めます。デフォルトでは、クラスのプロパティは永続と見なされません：

    <hibernate-mapping package="org.hibernate.tutorial.domain">

        <class name="Event" table="EVENTS">

            <id name="id" column="EVENT_ID">

                <generator class="native"/>

            </id>

            <property name="date" type="timestamp" column="EVENT_DATE"/>

            <property name="title"/>

        </class>

    </hibernate-mapping>

`id` 要素の場合と同様に、 `property` 要素の `name` 属性で、どのゲッターとセッターメソッドを使うべきかを Hibernate に教えます。この例では、 Hibernate は `getDate()/setDate()` と `getTitle()/setTitle()` を探します。

## 注意

なぜ `date` プロパティのマッピングには `column` 属性があり、 `title` プロパティにはないのでしょうか？ `column` 属性がなければ、 Hibernate はデフォルトでプロパティ名をカラム名として使います。これは `title` では上手くいきます。しかし `date` は、ほとんどのデータベースで予約語なので、違う名前でマッピングした方がよいのです。

次に興味深いのは `title` マッピングが `type` 属性をも欠いている点です。マッピングファイルで宣言して使う type は、おわかりかもしれませんが Java のデータ型ではありません。 SQL データベースの型でもありません。これは Hibernateマッピング型 と呼ばれる、 Java から SQL データの型へまたは SQL から Java データ型へ翻訳するコンバータです。繰り返しになりますが、 Hibernate は `type` 属性がマッピングファイル内になければ、正しいコンバージョンとマッピング型を自分で解決しようとします。 （Javaクラスのリフレクションを使った）この自動検知は、場合によってはあなたが期待または必要とするデフォルト値にならないかもしれません。 `date` プロパティの場合がそうでした。 Hibernate はこの（ `java.util.Date` の）プロパティを SQL の `date` , `timestamp` , `time` のうち、どのカラムにマッピングするべきなのかわかりません。 `timestamp` コンバータでプロパティをマッピングすることにより、完全な日時を保存します。

## ティップ

Hibernate makes this mapping type determination using reflection when the mapping files are processed. This can take time and resources, so if startup performance is important you should consider explicitly defining the type to use.

Save this mapping file as `src/main/resources/org/hibernate/tutorial/domain/Event.hbm.xml`.

### 1.1.4. Hibernate の設定

At this point, you should have the persistent class and its mapping file in place. It is now time to configure Hibernate. First let's set up HSQLDB to run in "server mode"

## 注意

We do this do that the data remains between runs.

We will utilize the Maven exec plugin to launch the HSQLDB server by running: `mvn exec:java -Dexec.mainClass="org.hsqldb.Server" -Dexec.args="-database.0 file:target/data/tutorial"` You will see it start up and bind to a TCP/IP socket; this is where our application will connect later. If you want to start with a fresh database during this tutorial, shutdown HSQLDB, delete all files in the `target/data` directory, and start HSQLDB again.

Hibernate will be connecting to the database on behalf of your application, so it needs to know how to obtain connections. For this tutorial we will be using a standalone connection pool (as opposed to a `javax.sql.DataSource`). Hibernate comes with support for two third-party open source JDBC connection pools: c3p0 and proxool. However, we will be using the Hibernate built-in connection pool for this tutorial.

## 注意

The built-in Hibernate connection pool is in no way intended for production use. It lacks several features found on any decent connection pool.

Hibernate の設定では、単純な `hibernate.properties` ファイル、それより少し洗練されている `hibernate.cfg.xml` ファイル、または完全にプログラム上でセットアップする方法が利用できます。ほとんどのユーザーが好むのは XML 設定ファイルです：

    <?xml version='1.0' encoding='utf-8'?>

    <!DOCTYPE hibernate-configuration PUBLIC

            "-//Hibernate/Hibernate Configuration DTD 3.0//EN"

            "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

    <hibernate-configuration>

        <session-factory>

            <!-- Database connection settings -->

            <property name="connection.driver_class"

    >org.hsqldb.jdbcDriver</property>

            <property name="connection.url"

    >jdbc:hsqldb:hsql://localhost</property>

            <property name="connection.username"

    >sa</property>

            <property name="connection.password"

    ></property>

            <!-- JDBC connection pool (use the built-in) -->

            <property name="connection.pool_size"

    >1</property>

            <!-- SQL dialect -->

            <property name="dialect"

    >org.hibernate.dialect.HSQLDialect</property>

            <!-- Enable Hibernate's automatic session context management -->

            <property name="current_session_context_class"

    >thread</property>

            <!-- Disable the second-level cache  -->

            <property name="cache.provider_class"

    >org.hibernate.cache.NoCacheProvider</property>

            <!-- Echo all executed SQL to stdout -->

            <property name="show_sql"

    >true</property>

            <!-- Drop and re-create the database schema on startup -->

            <property name="hbm2ddl.auto"

    >update</property>

            <mapping resource="org/hibernate/tutorial/domain/Event.hbm.xml"/>

        </session-factory>

    </hibernate-configuration

    >

## 注意

この XML の設定が異なる DTD を使うことに注意してください。

特定のデータベースを受け持つグローバルファクトリである Hibernate の `SessionFactory` を設定します。もし複数のデータベースがある場合には、 （スタートアップを簡単にするため）通常いくつかの設定ファイル内で、いくつかの `<session-factory>` を使う設定にしてください。

最初の4つの `property` 要素は JDBC コネクションに必要な設定を含んでいます。 dialect という名前の `property` 要素は、 Hibernate が生成する特定の SQL 方言を指定します。

## ティップ

In most cases, Hibernate is able to properly determine which dialect to use. See 「Dialect resolution」 for more information.

永続的なコンテキストに対する Hibernate のセッションの自動管理は、後の例ですぐにわかるように、役に立つことでしょう。 `hbm2ddl.auto` オプションはデータベーススキーマの自動生成を on にします。これは直接データベースに対して生成されます。当然（config オプションを削除して） off にしたり、 `SchemaExport` という Ant タスクの助けを借りてファイルにリダイレクトしたりできます。最後に永続クラスのためのマッピングファイルを設定に追加します。

Save this file as `hibernate.cfg.xml` into the `src/main/resources` directory.

### 1.1.5. Maven によるビルド

We will now build the tutorial with Maven. You will need to have Maven installed; it is available from the Maven download page. Maven will read the `/pom.xml` file we created earlier and know how to perform some basic project tasks. First, lets run the `compile` goal to make sure we can compile everything so far:

    [hibernateTutorial]$ mvn compile
    [INFO] Scanning for projects...
    [INFO] ------------------------------------------------------------------------
    [INFO] Building First Hibernate Tutorial
    [INFO]    task-segment: [compile]
    [INFO] ------------------------------------------------------------------------
    [INFO] [resources:resources]
    [INFO] Using default encoding to copy filtered resources.
    [INFO] [compiler:compile]
    [INFO] Compiling 1 source file to /home/steve/projects/sandbox/hibernateTutorial/target/classes
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESSFUL
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 2 seconds
    [INFO] Finished at: Tue Jun 09 12:25:25 CDT 2009
    [INFO] Final Memory: 5M/547M
    [INFO] ------------------------------------------------------------------------

### 1.1.6. スタートアップとヘルパ

さて `Event` オブジェクトをロードしたり格納したりする準備ができました。しかしまずはインフラストラクチャのコードを書いて、セットアップを完了する必要があります。まずは Hibernate をスタートアップしなければなりません。このスタートアップには、グローバルの `SessionFactory` オブジェクトを生成して、それをアプリケーションのコードでアクセスしやすい場所に格納することが含まれます。 `org.hibernate.SessionFactory` は新しく `org.hibernate.Session` をオープンすることができます。 `org.hibernate.Session` はシングルスレッドの作業単位(Unit of Work)を表現します。それに対し `org.hibernate.SessionFactory` はスレッドセーフのグローバルオブジェクトであり、一度だけインスタンス化されます。

ここでスタートアップを行い、便利に `org.hibernate.SessionFactory` へアクセスする `HibernateUtil` ヘルパクラスを作成します。実装を見てみましょう：

    package org.hibernate.tutorial.util;

    import org.hibernate.SessionFactory;

    import org.hibernate.cfg.Configuration;

    public class HibernateUtil {

        private static final SessionFactory sessionFactory = buildSessionFactory();

        private static SessionFactory buildSessionFactory() {

            try {

                // Create the SessionFactory from hibernate.cfg.xml

                return new Configuration().configure().buildSessionFactory();

            }

            catch (Throwable ex) {

                // Make sure you log the exception, as it might be swallowed

                System.err.println("Initial SessionFactory creation failed." + ex);

                throw new ExceptionInInitializerError(ex);

            }

        }

        public static SessionFactory getSessionFactory() {

            return sessionFactory;

        }

    }

Save this code as `src/main/java/org/hibernate/tutorial/util/HibernateUtil.java`

This class not only produces the global `org.hibernate.SessionFactory` reference in its static initializer; it also hides the fact that it uses a static singleton. We might just as well have looked up the `org.hibernate.SessionFactory` reference from JNDI in an application server or any other location for that matter.

If you give the `org.hibernate.SessionFactory` a name in your configuration, Hibernate will try to bind it to JNDI under that name after it has been built. Another, better option is to use a JMX deployment and let the JMX-capable container instantiate and bind a `HibernateService` to JNDI. Such advanced options are discussed later.

You now need to configure a logging system. Hibernate uses commons logging and provides two choices: Log4j and JDK 1.4 logging. Most developers prefer Log4j: copy `log4j.properties` from the Hibernate distribution in the `etc/` directory to your `src` directory, next to `hibernate.cfg.xml`. If you prefer to have more verbose output than that provided in the example configuration, you can change the settings. By default, only the Hibernate startup message is shown on stdout.

チュートリアルのインフラは完全です。 Hibernate を使って実際の作業をする準備が整いました。

### 1.1.7. オブジェクトのロードと格納

We are now ready to start doing some real work with Hibernate. Let's start by writing an `EventManager` class with a `main()` method:

    package org.hibernate.tutorial;

    import org.hibernate.Session;

    import java.util.*;

    import org.hibernate.tutorial.domain.Event;

    import org.hibernate.tutorial.util.HibernateUtil;

    public class EventManager {

        public static void main(String[] args) {

            EventManager mgr = new EventManager();

            if (args[0].equals("store")) {

                mgr.createAndStoreEvent("My Event", new Date());

            }

            HibernateUtil.getSessionFactory().close();

        }

        private void createAndStoreEvent(String title, Date theDate) {

            Session session = HibernateUtil.getSessionFactory().getCurrentSession();

            session.beginTransaction();

            Event theEvent = new Event();

            theEvent.setTitle(title);

            theEvent.setDate(theDate);

            session.save(theEvent);

            session.getTransaction().commit();

        }

    }

In `createAndStoreEvent()` we created a new `Event` object and handed it over to Hibernate. At that point, Hibernate takes care of the SQL and executes an `INSERT` on the database.

A org.hibernate.Session is designed to represent a single unit of work (a single atomic piece of work to be performed). For now we will keep things simple and assume a one-to-one granularity between a Hibernate org.hibernate.Session and a database transaction. To shield our code from the actual underlying transaction system we use the Hibernate `org.hibernate.Transaction` API. In this particular case we are using JDBC-based transactional semantics, but it could also run with JTA.

What does `sessionFactory.getCurrentSession()` do? First, you can call it as many times and anywhere you like once you get hold of your `org.hibernate.SessionFactory`. The `getCurrentSession()` method always returns the "current" unit of work. Remember that we switched the configuration option for this mechanism to "thread" in our `src/main/resources/hibernate.cfg.xml`? Due to that setting, the context of a current unit of work is bound to the current Java thread that executes the application.

## 重要項目

Hibernate offers three methods of current session tracking. The "thread" based method is not intended for production use; it is merely useful for prototyping and tutorials such as this one. Current session tracking is discussed in more detail later on.

A org.hibernate.Session begins when the first call to `getCurrentSession()` is made for the current thread. It is then bound by Hibernate to the current thread. When the transaction ends, either through commit or rollback, Hibernate automatically unbinds the org.hibernate.Session from the thread and closes it for you. If you call `getCurrentSession()` again, you get a new org.hibernate.Session and can start a new unit of work.

作業単位 (Unit of Work) の範囲に関して、 Hibernate の org.hibernate.Session は1つまたはいくつかのデータベースオペレーションを実行するために使用されるべきでしょうか？上記の例は、１つのオペレーションで1つの org.hibernate.Session を使用します。これは純粋な偶然で、例はその他のアプローチを示すほど込み入っていません。 Hibernate の org.hibernate.Session の範囲は柔軟ですが、 全ての データベースオペレーションのために新しい Hibernate org.hibernate.Session を使用するようにアプリケーションをデザインするべきではありません。従って、もしそれを以下の (普通の) 例で何度か見たとしても、アンチパターンである オペレーション毎の Session を考慮してください。実際の (ウェブ) アプリケーションは、このチュートリアルで後に見ることができます。

See 13章Transactions and Concurrency for more information about transaction handling and demarcation. The previous example also skipped any error handling and rollback.

To run this, we will make use of the Maven exec plugin to call our class with the necessary classpath setup: `mvn exec:java -Dexec.mainClass="org.hibernate.tutorial.EventManager" -Dexec.args="store"`

## 注意

You may need to perform `mvn compile` first.

コンパイルすると、 Hibernate がスタートし、設定によりますが、多くのログ出力があるはずです。その最後には以下の行があるでしょう：

    [java] Hibernate: insert into EVENTS (EVENT_DATE, title, EVENT_ID) values (?, ?, ?)

This is the `INSERT` executed by Hibernate.

To list stored events an option is added to the main method:

            if (args[0].equals("store")) {

                mgr.createAndStoreEvent("My Event", new Date());

            }

            else if (args[0].equals("list")) {

                List events = mgr.listEvents();

                for (int i = 0; i < events.size(); i++) {

                    Event theEvent = (Event) events.get(i);

                    System.out.println(

                            "Event: " + theEvent.getTitle() + " Time: " + theEvent.getDate()

                    );

                }

            }

新しい `listEvents()メソッド` も追加します。

        private List listEvents() {

            Session session = HibernateUtil.getSessionFactory().getCurrentSession();

            session.beginTransaction();

            List result = session.createQuery("from Event").list();

            session.getTransaction().commit();

            return result;

        }

Here, we are using a Hibernate Query Language (HQL) query to load all existing `Event` objects from the database. Hibernate will generate the appropriate SQL, send it to the database and populate `Event` objects with the data. You can create more complex queries with HQL. See 16章HQL: Hibernate クエリ言語 for more information.

Now we can call our new functionality, again using the Maven exec plugin: `mvn exec:java -Dexec.mainClass="org.hibernate.tutorial.EventManager" -Dexec.args="list"`

## 1.2. パート2 - 関連のマッピング

永続エンティティクラスをテーブルにマッピングしました。さらにこの上にいくつかのクラスの関連を追加しましょう。まず初めにアプリケーションに人々を追加し、彼らが参加するイベントのリストを格納します。

### 1.2.1. Person クラスのマッピング

最初の `Person` クラスは単純です：

    package org.hibernate.tutorial.domain;

    public class Person {

        private Long id;

        private int age;

        private String firstname;

        private String lastname;

        public Person() {}

        // Accessor methods for all properties, private setter for 'id'

    }

Save this to a file named `src/main/java/org/hibernate/tutorial/domain/Person.java`

Next, create the new mapping file as `src/main/resources/org/hibernate/tutorial/domain/Person.hbm.xml`

    <hibernate-mapping package="org.hibernate.tutorial.domain">

        <class name="Person" table="PERSON">

            <id name="id" column="PERSON_ID">

                <generator class="native"/>

            </id>

            <property name="age"/>

            <property name="firstname"/>

            <property name="lastname"/>

        </class>

    </hibernate-mapping>

最後に Hibernate の設定に新しいマッピングを追加してください：

    <mapping resource="org/hibernate/tutorial/domain/Event.hbm.xml"/>

    <mapping resource="org/hibernate/tutorial/domain/Person.hbm.xml"/>

それではこれら2つのエンティティ間の関連を作成します。人々がイベントに参加でき、イベントが参加者を持つのは明らかです。扱わなければならない設計の問題は、方向、多重度、コレクションの振る舞いです。

### 1.2.2. 単方向 Set ベース関連

By adding a collection of events to the `Person` class, you can easily navigate to the events for a particular person, without executing an explicit query - by calling `Person#getEvents`. Multi-valued associations are represented in Hibernate by one of the Java Collection Framework contracts; here we choose a `java.util.Set` because the collection will not contain duplicate elements and the ordering is not relevant to our examples:

    public class Person {

        private Set events = new HashSet();

        public Set getEvents() {

            return events;

        }

        public void setEvents(Set events) {

            this.events = events;

        }

    }

Before mapping this association, let's consider the other side. We could just keep this unidirectional or create another collection on the `Event`, if we wanted to be able to navigate it from both directions. This is not necessary, from a functional perspective. You can always execute an explicit query to retrieve the participants for a particular event. This is a design choice left to you, but what is clear from this discussion is the multiplicity of the association: "many" valued on both sides is called a many-to-many association. Hence, we use Hibernate's many-to-many mapping:

    <class name="Person" table="PERSON">

        <id name="id" column="PERSON_ID">

            <generator class="native"/>

        </id>

        <property name="age"/>

        <property name="firstname"/>

        <property name="lastname"/>

        <set name="events" table="PERSON_EVENT">

            <key column="PERSON_ID"/>

            <many-to-many column="EVENT_ID" class="Event"/>

        </set>

    </class>

Hibernate はありとあらゆる種類のコレクションマッピングをサポートしていますが、最も一般的なものが `set` です。 多対多関連（または n:m エンティティリレーションシップ）には、関連テーブルが必要です。このテーブルのそれぞれの行は、人とイベント間のリンクを表現します。テーブル名は `set` 要素の `table` 属性で設定します。人側の関連の識別子カラム名は `key` 要素で、イベント側のカラム名は `many-to-many` の `column` 属性で定義します。 Hibernate にコレクションのオブジェクトのクラス （正確には、参照のコレクションの反対側のクラス）を教えなければなりません。

そのためこのマッピングのデータベーススキーマは以下のようになります：

        _____________        __________________
       |             |      |                  |       _____________
       |   EVENTS    |      |   PERSON_EVENT   |      |             |
       |_____________|      |__________________|      |    PERSON   |
       |             |      |                  |      |_____________|
       | *EVENT_ID   | <--> | *EVENT_ID        |      |             |
       |  EVENT_DATE |      | *PERSON_ID       | <--> | *PERSON_ID  |
       |  TITLE      |      |__________________|      |  AGE        |
       |_____________|                                |  FIRSTNAME  |
                                                      |  LASTNAME   |
                                                      |_____________|

### 1.2.3. 関連を働かせる

`EventManager` の新しいメソッドで人々とイベントを一緒にしましょう：

        private void addPersonToEvent(Long personId, Long eventId) {

            Session session = HibernateUtil.getSessionFactory().getCurrentSession();

            session.beginTransaction();

            Person aPerson = (Person) session.load(Person.class, personId);

            Event anEvent = (Event) session.load(Event.class, eventId);

            aPerson.getEvents().add(anEvent);

            session.getTransaction().commit();

        }

After loading a `Person` and an `Event`, simply modify the collection using the normal collection methods. There is no explicit call to `update()` or `save()`; Hibernate automatically detects that the collection has been modified and needs to be updated. This is called automatic dirty checking. You can also try it by modifying the name or the date property of any of your objects. As long as they are in persistent state, that is, bound to a particular Hibernate `org.hibernate.Session`, Hibernate monitors any changes and executes SQL in a write-behind fashion. The process of synchronizing the memory state with the database, usually only at the end of a unit of work, is called flushing. In our code, the unit of work ends with a commit, or rollback, of the database transaction.

異なる作業単位 (Unit of Work) で人々とイベントをロードすることも当然できます。そうでなければ、永続状態にないとき（以前に永続であったなら、この状態を 分離（detached） と呼びます）、 `org.hibernate.Session` の外部でオブジェクトを修正します。分離されるときにはコレクションを変更することも可能です：

        private void addPersonToEvent(Long personId, Long eventId) {

            Session session = HibernateUtil.getSessionFactory().getCurrentSession();

            session.beginTransaction();

            Person aPerson = (Person) session

                    .createQuery("select p from Person p left join fetch p.events where p.id = :pid")

                    .setParameter("pid", personId)

                    .uniqueResult(); // Eager fetch the collection so we can use it detached

            Event anEvent = (Event) session.load(Event.class, eventId);

            session.getTransaction().commit();

            // End of first unit of work

            aPerson.getEvents().add(anEvent); // aPerson (and its collection) is detached

            // Begin second unit of work

            Session session2 = HibernateUtil.getSessionFactory().getCurrentSession();

            session2.beginTransaction();

            session2.update(aPerson); // Reattachment of aPerson

            session2.getTransaction().commit();

        }

`update` の呼び出しは分離オブジェクトを再び永続化します。これは、新しい作業単位 (Unit of Work) にバインドすると言えるでしょう。そのため分離の間に加えられたどのような修正もデータベースにセーブできます。エンティティオブジェクトのコレクションへの修正（追加･削除）も同様にセーブできます。

これは今はあまり使いみちがありませんが、自分のアプリケーションの設計に組み込むことができる重要なコンセプトです。それではこのエクササイズの最後に、 `EventManager` のメインメソッドに新しいアクションを追加してコマンドラインから呼び出してみましょう。人やイベントの識別子が必要なら、 `save()` メソッドが返してくれます （場合によっては識別子を返すためにメソッドを修正する必要があるかもしれません）。

            else if (args[0].equals("addpersontoevent")) {

                Long eventId = mgr.createAndStoreEvent("My Event", new Date());

                Long personId = mgr.createAndStorePerson("Foo", "Bar");

                mgr.addPersonToEvent(personId, eventId);

                System.out.println("Added person " + personId + " to event " + eventId);

            }

これは同じように重要な2つのクラス、つまり2つのエンティティ間の関連の例でした。前に述べたように、典型的なモデルには、普通「比較的重要ではない」他のクラスと型があります。これまでに見たような `int` や `java.lang.String` のようなものです。このようなクラスを 値型 と言います。このインスタンスは特定のエンティティに 依存 します。この型のインスタンスは独自の ID を持ちませんし、エンティティ間で共有されることもありません （ファーストネームが同じだったとしても、2人の人は同じ `firstname` オブジェクトを参照しません）。値型はもちろん JDK 内に見つかりますが、それだけではなく （実際、 Hibernate アプリケーションにおいてすべての JDK クラスは値型と見なせます）、 例えば `Address` や `MonetaryAmount` のような独自の依存クラスを書くこともできます。

値型のコレクションを設計することもできます。これは他のエンティティへの参照のコレクションとは概念的に非常に異なりますが、 Java ではほとんど同じように見えます。

### 1.2.4. 値のコレクション

Let's add a collection of email addresses to the `Person` entity. This will be represented as a `java.util.Set` of `java.lang.String` instances:

        private Set emailAddresses = new HashSet();

        public Set getEmailAddresses() {

            return emailAddresses;

        }

        public void setEmailAddresses(Set emailAddresses) {

            this.emailAddresses = emailAddresses;

        }

この `Set` のマッピングです：

            <set name="emailAddresses" table="PERSON_EMAIL_ADDR">

                <key column="PERSON_ID"/>

                <element type="string" column="EMAIL_ADDR"/>

            </set>

前のマッピングと比べて違うのは `element` の部分ですが、 Hibernate にこのコレクションが他のエンティティへの参照を含まず、 `string` 型の要素のコレクションを含むことを教えます（小文字の名前 (string) は Hibernate のマッピング型またはコンバータであるということです）。繰り返しますが、`set` 要素の `table` 属性は、コレクションのためのテーブル名を指定します。 `key` 要素はコレクションテーブルの外部キーカラム名を定義します。 `element` 要素の `column` 属性は `string` の値が実際に格納されるカラムの名前を定義します。

更新したスキーマを見てください：

      _____________        __________________
     |             |      |                  |       _____________
     |   EVENTS    |      |   PERSON_EVENT   |      |             |       ___________________
     |_____________|      |__________________|      |    PERSON   |      |                   |
     |             |      |                  |      |_____________|      | PERSON_EMAIL_ADDR |
     | *EVENT_ID   | <--> | *EVENT_ID        |      |             |      |___________________|
     |  EVENT_DATE |      | *PERSON_ID       | <--> | *PERSON_ID  | <--> |  *PERSON_ID       |
     |  TITLE      |      |__________________|      |  AGE        |      |  *EMAIL_ADDR      |
     |_____________|                                |  FIRSTNAME  |      |___________________|
                                                    |  LASTNAME   |
                                                    |_____________|

コレクションテーブルの主キーは、実際は両方のカラムを使った複合キーであることがわかります。これは人ごとに E メールアドレスが重複できないということで、 Java の set に要求されるセマンティクスそのものです。

以前人とイベントを関連づけたときと全く同じように、今や試しにコレクションに要素を追加することができるようになりました。 両方とも Java では同じコードです。

        private void addEmailToPerson(Long personId, String emailAddress) {

            Session session = HibernateUtil.getSessionFactory().getCurrentSession();

            session.beginTransaction();

            Person aPerson = (Person) session.load(Person.class, personId);

            // adding to the emailAddress collection might trigger a lazy load of the collection

            aPerson.getEmailAddresses().add(emailAddress);

            session.getTransaction().commit();

        }

This time we did not use a fetch query to initialize the collection. Monitor the SQL log and try to optimize this with an eager fetch.

### 1.2.5. 双方向関連

次に双方向関連をマッピングします。 Java で両側から人とイベントの関連を動作させます。もちろん、データベーススキーマは変わりませんが、多重度は多対多のままです。

## 注意

リレーショナルデータベースはネットワークプログラミング言語よりも柔軟なので、ナビゲーションの方向のようなものを必要としません。データはあらゆる方法で見たり復元できるということです。

まず `Event` イベントクラスに参加者のコレクションを追加します：

        private Set participants = new HashSet();

        public Set getParticipants() {

            return participants;

        }

        public void setParticipants(Set participants) {

            this.participants = participants;

        }

それでは `Event.hbm.xml` で関連のこちら側をマッピングしてください。

            <set name="participants" table="PERSON_EVENT" inverse="true">

                <key column="EVENT_ID"/>

                <many-to-many column="PERSON_ID" class="Person"/>

            </set

    >

ご覧のとおり、いずれのマッピングドキュメント (XMLファイル) でも、普通の `set` マッピングを使っています。 `key` と `many-to-many` のカラム名が、両方のマッピングドキュメントで入れ替えになっていることに注目してください。ここで最も重要な追加項目は、 `Event` のコレクションマッピングの `set` 要素にある `inverse="true"` 属性です。

この指定の意味は、2つの間のエンティティ間のリンクについての情報を探す必要があるとき、 Hibernate は反対側のエンティティ、つまり `Person` クラスから探すということです。一度2つのエンティティ間の双方向リンクがどのように作成されるかがわかれば、これを理解することはとても簡単です。

### 1.2.6. 双方向リンクの動作

まず、 Hibernate が通常の Java のセマンティクスに影響を及ぼさないことを心に留めておいてください。私たちは、単方向の例としてどのように `Person` と `Event` の間のリンクを作成したでしょうか？ `Person` のインスタンスのイベントへの参照のコレクションに `Event` のインスタンスを追加しました。そのためこのリンクを双方向にしたければ、当たり前ですが反対側にも同じことをしなければなりません。 `Event` のコレクションに `Person` への参照を追加するということです。この「両側でリンクを設定すること」は絶対に必要なので、決して忘れないでください。

多くの開発者は慎重にプログラムするので、エンティティの両側に正しく関連を設定するリンク管理メソッドを作成します。例えば `Person` では以下のようになります。：

        protected Set getEvents() {

            return events;

        }

        protected void setEvents(Set events) {

            this.events = events;

        }

        public void addToEvent(Event event) {

            this.getEvents().add(event);

            event.getParticipants().add(this);

        }

        public void removeFromEvent(Event event) {

            this.getEvents().remove(event);

            event.getParticipants().remove(this);

        }

コレクションのゲットとセットメソッドが現在 protected になっていることに注意してください。これは同じパッケージのクラスやサブクラスのメソッドは依然アクセスが可能ですが、 （ほとんど） そのパッケージ外のどのクラスでも直接そのコレクションを台無しにすることを防ぎます。おそらく反対側のコレクションにも同じことをした方がいいでしょう。

`inverse` マッピング属性とはいったい何でしょうか？開発者と Java にとっては、双方向リンクは単に両側の参照を正しく設定するということです。しかし Hibernate は（制約違反を避けるために） SQL の `INSERT` と `UPDATE` 文を正確に変更するための十分な情報を持っていないので、双方向関連プロパティを扱うための何らかの助けを必要とします。関連の片側を `inverse` に設定することで、 Hibernate は基本的には設定した側を無視し、反対側の 鏡 として考えます。これだけで、 Hibernate は方向を持つナビゲーションモデルを SQL データベーススキーマへ変換するときのすべての問題にうまく対処できます。覚えておかなければならないルールは簡単です。双方向関連は必ず片側を `inverse` にする必要があるということです。一対多関連ではそれは多側でなければなりません。多対多関連ではどちら側でも構いません。どちらでも違いはありません。

## 1.3. パート3 - EventManager Web アプリケーション

Hibernate の Web アプリケーションは、スタンドアローンのアプリケーションのように `Session` と `Transaction` を使用します。しかしいくつかの一般的なパターンが役立ちます。ここで `EventManagerServlet` を作成します。このサーブレットは、データベースに格納した全てのイベントをリストにでき、さらに HTML フォームから新しいイベントを入力できるものです。

### 1.3.1. 基本的な Servlet の記述

Servlet は HTTP の `GET` リクエストのみを処理するので、 `doGet()` を実装します。

    package org.hibernate.tutorial.web;

    // Imports

    public class EventManagerServlet extends HttpServlet {

        protected void doGet(

                HttpServletRequest request,

                HttpServletResponse response) throws ServletException, IOException {

            SimpleDateFormat dateFormatter = new SimpleDateFormat( "dd.MM.yyyy" );

            try {

                // Begin unit of work

                HibernateUtil.getSessionFactory().getCurrentSession().beginTransaction();

                // Process request and render page...

                // End unit of work

                HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().commit();

            }

            catch (Exception ex) {

                HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().rollback();

                if ( ServletException.class.isInstance( ex ) ) {

                    throw ( ServletException ) ex;

                }

                else {

                    throw new ServletException( ex );

                }

            }

        }

    }

Save this servlet as `src/main/java/org/hibernate/tutorial/web/EventManagerServlet.java`

これは session-per-request というパターンです。 Servlet がリクエストを受け取ると、 `SessionFactory` の `getCurrentSession()` の最初の呼び出しで、 Hibernate の新しい `Session` が開かれます。そのときデータベーストランザクションが開始されます。データの読み書きに関わらず、すべてのデータアクセスはトランザクション内で行います（アプリケーション内ではオートコミットモードを使用しません）。

全てのデータベースオペレーションで新しい Hibernate `Session` を使用 しないでください 。全てのリクエストで機能する、１つの Hibernate `Session` を使用してください。自動的に現在の Java スレッドにバインドされるので、 `getCurrentSession()` を使用してください。

次に、リクエストのアクションは処理され、レスポンスである HTML が描画されます。これについてはすぐに説明します。

最後にリクエストの処理と HTML 描画が完了したときに、作業単位 (Unit of Work) を終了します。もし処理や描画中に問題が発生した場合、例外が送出されててデータベーストランザクションをロールバックします。これで `session-per-request` パターンが完了します。全てのサーブレットにトランザクション境界のコードを書く代わりに、サーブレットフィルタに記述することも可能です。 Open Session in View と呼ばれるこのパターンについては、 Hibernate の Web サイトや Wiki を参照してください。サーブレットではなく JSP で HTML 描画をしようとすると、すぐにこのパターンについての情報が必要になるでしょう。

### 1.3.2. 処理と描画

では、リクエストの処理とページの描画を実装します。

            // Write HTML header

            PrintWriter out = response.getWriter();

            out.println("<html><head><title>Event Manager</title></head><body>");

            // Handle actions

            if ( "store".equals(request.getParameter("action")) ) {

                String eventTitle = request.getParameter("eventTitle");

                String eventDate = request.getParameter("eventDate");

                if ( "".equals(eventTitle) || "".equals(eventDate) ) {

                    out.println("<b><i>Please enter event title and date.</i></b>");

                }

                else {

                    createAndStoreEvent(eventTitle, dateFormatter.parse(eventDate));

                    out.println("<b><i>Added event.</i></b>");

                }

            }

            // Print page

           printEventForm(out);

           listEvents(out, dateFormatter);

           // Write HTML footer

           out.println("</body></html>");

           out.flush();

           out.close();

Java と HTML が混在するコーディングスタイルは、より複雑なアプリケーションには適していないでしょう （このチュートリアルでは、基本的な Hibernate のコンセプトを示しているだけであることを覚えておいてください）。このコードは HTML のヘッダーとフッターの記述です。このページには、イベントを入力する HTML フォームと、データベースにある全てのイベントのリストが表示されます。最初のメソッドはごく単純な HTML 出力です。

        private void printEventForm(PrintWriter out) {

            out.println("<h2>Add new event:</h2>");

            out.println("<form>");

            out.println("Title: <input name='eventTitle' length='50'/><br/>");

            out.println("Date (e.g. 24.12.2009): <input name='eventDate' length='10'/><br/>");

            out.println("<input type='submit' name='action' value='store'/>");

            out.println("</form>");

        }

`listEvents()` メソッドは、現在のスレッドに結びつく Hibernate の `Session` を使用して、クエリを実行します。

        private void listEvents(PrintWriter out, SimpleDateFormat dateFormatter) {

            List result = HibernateUtil.getSessionFactory()

                    .getCurrentSession().createCriteria(Event.class).list();

            if (result.size() > 0) {

                out.println("<h2>Events in database:</h2>");

                out.println("<table border='1'>");

                out.println("<tr>");

                out.println("<th>Event title</th>");

                out.println("<th>Event date</th>");

                out.println("</tr>");

                Iterator it = result.iterator();

                while (it.hasNext()) {

                    Event event = (Event) it.next();

                    out.println("<tr>");

                    out.println("<td>" + event.getTitle() + "</td>");

                    out.println("<td>" + dateFormatter.format(event.getDate()) + "</td>");

                    out.println("</tr>");

                }

                out.println("</table>");

            }

        }

最後に、 `store` アクションが `createAndStoreEvent()` メソッドを呼び出します。このメソッドでも現在のスレッドの `Session` を利用します。

        protected void createAndStoreEvent(String title, Date theDate) {

            Event theEvent = new Event();

            theEvent.setTitle(title);

            theEvent.setDate(theDate);

            HibernateUtil.getSessionFactory()

                    .getCurrentSession().save(theEvent);

        }

これでサーブレットの完成です。サーブレットへのリクエストは、1つの `Session` と `Transaction` で処理されるでしょう。最初のスタンドアローンのアプリケーションのように、 Hibernate は自動的にこれらのオブジェクトを実行するスレッドに結び付けることができます。これにより、開発者が自由にコードをレイヤー分けでき、好きな方法で `SessionFactory` へのアクセスができるようになります。通常、開発者はより洗練されたデザインを使用して、データアクセスのコードをデータアクセスオブジェクトに移動するでしょう（DAOパターン）。より多くの例は、 Hibernate の Wiki を参照してください。

### 1.3.3. デプロイとテスト

To deploy this application for testing we must create a Web ARchive (WAR). First we must define the WAR descriptor as `src/main/webapp/WEB-INF/web.xml`

    <?xml version="1.0" encoding="UTF-8"?>

    <web-app version="2.4"

        xmlns="http://java.sun.com/xml/ns/j2ee"

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

        <servlet>

            <servlet-name>Event Manager</servlet-name>

            <servlet-class>org.hibernate.tutorial.web.EventManagerServlet</servlet-class>

        </servlet>

        <servlet-mapping>

            <servlet-name>Event Manager</servlet-name>

            <url-pattern>/eventmanager</url-pattern>

        </servlet-mapping>

    </web-app>

ビルドとデプロイのために、プロジェクトディレクトリで `mvn package` を呼び出し、 `hibernate-tutorial.war` ファイルを Tomcat の `webapp` ディレクトリにコピーしてください。

## 注意

If you do not have Tomcat installed, download it from http://tomcat.apache.org/ and follow the installation instructions. Our application requires no changes to the standard Tomcat configuration.

一度デプロイして Tomcat を起動すれば、 `http://localhost:8080/hibernate-tutorial/eventmanager` でアプリケーションへのアクセスが可能です。最初のリクエストが作成したサーブレットに渡ったときに、 Tomcat のログで Hibernate の初期化処理を確認してください （ `HibernateUtil` 内の静的初期化ブロックが呼ばれています）。また、例外が発生したなら詳細を確認してください。

## 1.4. 要約

このチュートリアルでは、簡単なスタンドアローンの Hibernate アプリケーションと小規模の Web アプリケーションを書くための基本を紹介しました。

## 第2章 アーキテクチャ

## 2.1. 概観

Hibernate アーキテクチャの（非常に）高いレベルからのビュー：

Unfortunately we cannot provide a detailed view of all possible runtime architectures. Hibernate is sufficiently flexible to be used in a number of ways in many, many architectures. We will, however, illustrate 2 specifically since they are extremes.

### 2.1.1. Minimal architecture

The "minimal" architecture has the application manage its own JDBC connections and provide those connections to Hibernate; additionally the application manages transactions for itself. This approach uses a minimal subset of Hibernate APIs.

### 2.1.2. Comprehensive architecture

The "comprehensive" architecture abstracts the application away from the underlying JDBC/JTA APIs and allows Hibernate to manage the details.

### 2.1.3. Basic APIs

Here are quick discussions about some of the API objects depicted in the preceding diagrams (you will see them again in more detail in later chapters).

SessionFactory (`org.hibernate.SessionFactory`)

  A thread-safe, immutable cache of compiled mappings for a single database. A factory for `org.hibernate.Session` instances. A client of `org.hibernate.connection.ConnectionProvider`. Optionally maintains a `second level cache` of data that is reusable between transactions at a process or cluster level.

Session (`org.hibernate.Session`)

  A single-threaded, short-lived object representing a conversation between the application and the persistent store. Wraps a JDBC `java.sql.Connection`. Factory for `org.hibernate.Transaction`. Maintains a `first level cache` of persistent the application's persistent objects and collections; this cache is used when navigating the object graph or looking up objects by identifier.

Persistent objects と Collections

  Short-lived, single threaded objects containing persistent state and business function. These can be ordinary JavaBeans/POJOs. They are associated with exactly one `org.hibernate.Session`. Once the `org.hibernate.Session` is closed, they will be detached and free to use in any application layer (for example, directly as data transfer objects to and from presentation). 11章オブジェクトを扱う discusses transient, persistent and detached object states.

Transient と detached な objects と Collections

  Instances of persistent classes that are not currently associated with a `org.hibernate.Session`. They may have been instantiated by the application and not yet persisted, or they may have been instantiated by a closed `org.hibernate.Session`. 11章オブジェクトを扱う discusses transient, persistent and detached object states.

Transaction (`org.hibernate.Transaction`)

  (Optional) A single-threaded, short-lived object used by the application to specify atomic units of work. It abstracts the application from the underlying JDBC, JTA or CORBA transaction. A `org.hibernate.Session` might span several `org.hibernate.Transaction`s in some cases. However, transaction demarcation, either using the underlying API or `org.hibernate.Transaction`, is never optional.

ConnectionProvider (`org.hibernate.connection.ConnectionProvider`)

  (Optional) A factory for, and pool of, JDBC connections. It abstracts the application from underlying `javax.sql.DataSource` or `java.sql.DriverManager`. It is not exposed to application, but it can be extended and/or implemented by the developer.

TransactionFactory (`org.hibernate.TransactionFactory`)

  (Optional) A factory for `org.hibernate.Transaction` instances. It is not exposed to the application, but it can be extended and/or implemented by the developer.

Extension Interfaces

  Hibernate は、永続層の振る舞いをカスタマイズするために、多くのオプション拡張インタフェースを用意しています。詳細は API ドキュメントを参照してください。

## 2.2. JMX との統合

JMX は Java コンポーネント管理の J2EE 標準です。 JMX 標準サービスを通して、 Hibernate は管理されます。ディストリビューションの中に `org.hibernate.jmx.HibernateService` という MBean 実装を用意しています。

Another feature available as a JMX service is runtime Hibernate statistics. See 「Hibernate 統計」 for more information.

## 2.3. コンテキスト上のセッション

Hibernate を使ったアプリケーションは、ほとんど、なんらかの形で「コンテキスト上の」セッションが必要になります。「コンテキスト上のセッション」は、特定のコンテキストのスコープのなかで有効なセッションのことです。しかし、通常アプリケーションごとにコンテキストを構成するものの定義は異なります。しかも、異なる複数のコンテキストは、現時点に対して異なるスコープを定義します。バージョン3.0より前の Hibernate では、自作の `ThreadLocal` ベースの「コンテキスト上のセッション」を利用するか、 `HibernateUtil` のようなヘルパークラスを利用するか、 proxy/interception ベースの「コンテキスト上のセッション」を提供する （Spring や Pico のような）サードパーティのフレームワークを利用するかのいずれかでした。

Starting with version 3.0.1, Hibernate added the `SessionFactory.getCurrentSession()` method. Initially, this assumed usage of `JTA` transactions, where the `JTA` transaction defined both the scope and context of a current session. Given the maturity of the numerous stand-alone `JTA TransactionManager` implementations, most, if not all, applications should be using `JTA` transaction management, whether or not they are deployed into a `J2EE` container. Based on that, the `JTA`-based contextual sessions are all you need to use.

しかし、バージョン 3.1 からは、 `SessionFactory.getCurrentSession()` の後の処理が、プラガブルになりました。これを受けて、現在のセッションを定義するスコープとコンテキストのプラガビリティを可能にするために、新しい拡張インタフェース ( `org.hibernate.context.CurrentSessionContext` ) と新しい構成パラメータ ( `hibernate.current_session_context_class` ) が追加されました。

See the Javadocs for the `org.hibernate.context.CurrentSessionContext` interface for a detailed discussion of its contract. It defines a single method, `currentSession()`, by which the implementation is responsible for tracking the current contextual session. Out-of-the-box, Hibernate comes with three implementations of this interface:

- `org.hibernate.context.JTASessionContext` - `JTA` トランザクションによって、現在のセッションが追跡され、スコープを決められます。この処理は、古い JTA だけのアプローチとまったく同じです。詳細は Javadoc を参照してください。

- `org.hibernate.context.ThreadLocalSessionContext` - スレッドの実行によって、現在のセッションが追跡されます。詳細は Javadoc を参照してください。

- `org.hibernate.context.ManagedSessionContext` - スレッドの実行によって、現在のセッションが追跡されます。しかし、このクラスの static メソッドで `Session` インスタンスをバインド/アンバインドする責任はあなたにあります。これは決して `Session` をオープン、フラッシュ、クローズしません。

The first two implementations provide a "one session - one database transaction" programming model. This is also known and used as session-per-request. The beginning and end of a Hibernate session is defined by the duration of a database transaction. If you use programmatic transaction demarcation in plain JSE without JTA, you are advised to use the Hibernate `Transaction` API to hide the underlying transaction system from your code. If you use JTA, you can utilize the JTA interfaces to demarcate transactions. If you execute in an EJB container that supports CMT, transaction boundaries are defined declaratively and you do not need any transaction or session demarcation operations in your code. Refer to 13章Transactions and Concurrency for more information and code examples.

`hibernate.current_session_context_class` 設定パラメータは、 `org.hibernate.context.CurrentSessionContext` のどの実装を使うかを指定します。下位互換性のため、このパラメータが設定されず `org.hibernate.transaction.TransactionManagerLookup` が設定されていた場合、 Hibernate は `org.hibernate.context.JTASessionContext` を使うことに注意してください。通常このパラメータの値には、3つの実装の中から使用する実装クラスの名前を直接指定します。しかし、"jta"、 "thread"、 "managed"というそれぞれの省略名も用意されています。

## 第3章 設定

Hibernate は様々な環境で動作するようにデザインされているため、非常に多くの設定要素があります。幸いなことに、 Hibernate は、公開されているパッケージの `etc/` フォルダの `hibernate.properties` に、ほとんどの設定要素の適切なデフォルト値が記述されています。この `hibernate.properties` をクラスパスに設定し、設定要素をカスタマイズするだけです。

## 3.1. プログラム上の設定

`org.hibernate.cfg.Configuration` のインスタンスは、 Java の型と SQL データベースのマッピング情報をすべて持っています。 `Configuration` は、（不変の） `SessionFactory` を生成するときに使用します。複数の XML マッピングファイルを変換し、マッピング情報にします。

通常、 `org.hibernate.cfg.Configuration` インスタンスは、特定の XML マッピングファイルによって直接初期化されます。もし、マッピングファイルがクラスパスに設定されている場合、次のメソッドを使ってください。 `addResource()` :

    Configuration cfg = new Configuration()

        .addResource("Item.hbm.xml")

        .addResource("Bid.hbm.xml");

代替案 (こちらのほうが良いときもあります) としてマッピングクラスを指定する方法もあります。 Hibernate に、マッピングファイルを 見つけさせてください：

    Configuration cfg = new Configuration()

        .addClass(org.hibernate.auction.Item.class)

        .addClass(org.hibernate.auction.Bid.class);

Hibernate は、クラスパスにある以下のような名前のマッピングファイルを見つけます。 `/org/hibernate/auction/Item.hbm.xml` 、 `/org/hibernate/auction/Bid.hbm.xml` 。この方法だと、ハードコーディングされたファイル名を排除できます。

`org.hibernate.cfg.Configuration` は、設定プロパティを指定することもできます：

    Configuration cfg = new Configuration()

        .addClass(org.hibernate.auction.Item.class)

        .addClass(org.hibernate.auction.Bid.class)

        .setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLInnoDBDialect")

        .setProperty("hibernate.connection.datasource", "java:comp/env/jdbc/test")

        .setProperty("hibernate.order_updates", "true");

Hibernate に設定プロパティを渡す方法は1つではありません。さまざまなオプションを用意しています：

1. `java.util.Properties` インスタンスを `Configuration.setProperties()` に渡します。

2. `hibernate.properties` をクラスパスのルートディレクトリに置きます。

3. `System` プロパティが `java -Dproperty=value` を使うように設定します。

4. `<property>` 要素を `hibernate.cfg.xml` （後述）に設定します。

If you want to get started quickly`hibernate.properties` is the easiest approach.

`org.hibernate.cfg.Configuration` は、起動時にだけあるオブジェクトであり、一度 `SessionFactory` を生成した後は、破棄されることを意図しています。

## 3.2. SessionFactory を取得する

When all mappings have been parsed by the `org.hibernate.cfg.Configuration`, the application must obtain a factory for `org.hibernate.Session` instances. This factory is intended to be shared by all application threads:

    SessionFactory sessions = cfg.buildSessionFactory();

Hibernate does allow your application to instantiate more than one `org.hibernate.SessionFactory`. This is useful if you are using more than one database.

## 3.3. JDBC コネクション

通常、開発者は `org.hibernate.SessionFactory` を生成し、 SessionFactory で JDBC コネクションをプーリングしたいと考えます。そのアプローチを採用する場合、単純に `org.hibernate.Session` をオープンしてください：

    Session session = sessions.openSession(); // open a new Session

これだけで、プーリングした JDBC コネクションを使って目的のデータベースにアクセスすることができます。

そのためには、 JDBC コネクションのプロパティを Hibernate に設定する必要があります。すべての Hibernate プロパティ名とセマンティクスは `org.hibernate.cfg.Environment` クラスに定義されています。この設定は JDBC コネクション設定の中で一番重要なものです。

もし、以下のプロパティを設定すると、 Hibernate はコネクションを取得するために（プールも） `java.sql.DriverManager` を使います:

表3.1 Hibernate JDBC プロパティ

プロパティ名 | 意味
--- | ---
hibernate.connection.driver_class | JDBC driver class
hibernate.connection.url | JDBC URL
hibernate.connection.username | データベースのユーザー
hibernate.connection.password | データベースユーザーパスワード
hibernate.connection.pool_size | maximum number of pooled connections

Hibernate のコネクションプールアルゴリズムは非常に初歩的なものです。これはすぐに始められるようにと用意されたもので、 製品として使用することを意図していません 。また、パフォーマンスのテストのためのものでもありません。最高のパフォーマンスと安定性を持ったプールを実現したければ、サードパーティのツールをお勧めします。 `hibernate.connection.pool_size` プロパティと適切なコネクションプールの設定を置き換えてください。これにより Hibernate のインターナルプールを無効にします。例えば次のように C3P0 を使います。

C3P0 はオープンソース JDBC コネクションプールで、 Hibernate の `lib` ディレクトリにあります。もし、 `hibernate.c3p0.*` プロパティをセットすれば、 Hibernate は、 `C3P0ConnectionProvider` を使います。もし Proxool を使いたい場合は、 `hibernate.properties` パッケージを参照したり、 Hibernate の Web サイトでより多くの情報を取得してください。

C3P0 用の `hibernate.properties` ファイルを例として示します：

    hibernate.connection.driver_class = org.postgresql.Driver
    hibernate.connection.url = jdbc:postgresql://localhost/mydatabase
    hibernate.connection.username = myuser
    hibernate.connection.password = secret
    hibernate.c3p0.min_size=5
    hibernate.c3p0.max_size=20
    hibernate.c3p0.timeout=1800
    hibernate.c3p0.max_statements=50
    hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect

アプリケーションサーバー上で使う場合は、 Hibernate を設定し、アプリケーションサーバーからコネクションを取得するようにしてください。 `javax.sql.Datasource` を JNDI に登録します。そしてプロパティを以下のように設定してください:

表3.2 Hibernate データソースプロパティ

プロパティ名 | 意味
--- | ---
hibernate.connection.datasource | データソースの JNDI 名
hibernate.jndi.url | JNDI プロバイダの URL (オプション)
hibernate.jndi.class | JNDI のクラス `InitialContextFactory` (オプション)
hibernate.connection.username | データベースユーザ (オプション)
hibernate.connection.password | データベースユーザのパスワード (オプション)

アプリケーションサーバーから提供された JNDI データソースを使う `hibernate.properties` ファイルの例を示します：

    hibernate.connection.datasource = java:/comp/env/jdbc/test
    hibernate.transaction.factory_class = \
        org.hibernate.transaction.JTATransactionFactory
    hibernate.transaction.manager_lookup_class = \
        org.hibernate.transaction.JBossTransactionManagerLookup
    hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect

JNDI データソースから取得した JDBC コネクションは、アプリケーションサーバーのコンテナ管理トランザクションに自動的に参加します。

任意のコネクションプロパティは、追加された "`hibernate.connnection`" プロパティ名によって与えられます。例えば、 charSet を設定したい場合は、 hibernate.connection.charSet を使います。

JDBC コネクションを取得する戦略を持つ独自のプラグインを定義する場合は、 `org.hibernate.connection.ConnectionProvider` インターフェースを実装してください。そして、実装クラスを hibernate.connection.provider_class に設定してください。

## 3.4. オプション設定プロパティ

これらのプロパティはランタイムに Hibernate の挙動を制御するものです。これらのプロパティはすべて妥当なデフォルト値があり、任意で設定します。

## 警告

Some of these properties are "system-level" only. System-level properties can be set only via `java -Dproperty=value` or `hibernate.properties`. They cannot be set by the other techniques described above.

表3.3 Hibernate 設定プロパティ

プロパティ名 | 意味
--- | ---
hibernate.dialect | Hibernate のクラス名 `org.hibernate.dialect.Dialect` が入ります。これはリレーショナルデータベースごとに最適化された SQL を生成します。 例 `full.classname.of.Dialect` In most cases Hibernate will actually be able to choose the correct `org.hibernate.dialect.Dialect` implementation based on the `JDBC metadata` returned by the JDBC driver.
hibernate.show_sql | 発行されたすべての SQL をコンソールに出力します。これはログカテゴリの `org.hibernate.SQL` に `debug` を設定する方法の代替手段です。 例 `true` | `false`
hibernate.format_sql | ログとコンソールの SQL を整形して表示します。 例 `true` | `false`
hibernate.default_schema | 生成される SQL 文のテーブルに設定するスキーマ/テーブルスペースです。 例.`SCHEMA_NAME`
hibernate.default_catalog | 生成される SQL 文のテーブルに設定するカタログです。 例 `CATALOG_NAME`
hibernate.session_factory_name | `org.hibernate.SessionFactory` は生成後、この名前で JNDI に自動的に登録されます。 例 `jndi/composite/name`
hibernate.max_fetch_depth | 外部結合フェッチの最大深度を設定します。結合する関連は対一関連のみ（一対一、多対一）です。 `0` を指定すると外部結合フェッチは無効になります。 例： 推奨する値は `0` から `3` の間です。
hibernate.default_batch_fetch_size | 関連フェッチのデフォルト Hibernate バッチサイズを指定します。 例： 推奨する値は `4` , `8` , `16` です。
hibernate.default_entity_mode | Sets a default mode for entity representation for all sessions opened from this `SessionFactory` `dynamic-map`, `dom4j`, `pojo`
hibernate.order_updates | 項目が更新されたときに、別の SQL で主キーを更新することを強制します。この場合、同時実行可能なシステムでは、まれにデッドロックが発生する可能性があります。 例 `true` | `false`
hibernate.generate_statistics | 有効の場合、 Hibernate はパフォーマンスチューニングに有効な統計情報を収集します。 例 `true` | `false`
hibernate.use_identifier_rollback | 有効の場合、オブジェクトが削除されたときに識別子プロパティをリセットし、デフォルト値にしたものを生成します。 例 `true` | `false`
hibernate.use_sql_comments | 有効の場合、 SQL 内にコメントを生成します。これはデバックを容易にします。デフォルトの値は `false` です。 例 `true` | `false`
hibernate.id.new_generator_mappings | Setting is relevant when using `@GeneratedValue`. It indicates whether or not the new `IdentifierGenerator` implementations are used for `javax.persistence.GenerationType.AUTO`, `javax.persistence.GenerationType.TABLE` and `javax.persistence.GenerationType.SEQUENCE`. Default to `false` to keep backward compatibility. 例 `true` | `false`

## 注意

We recommend all new projects which make use of to use `@GeneratedValue` to also set `hibernate.id.new_generator_mappings=true` as the new generators are more efficient and closer to the JPA 2 specification semantic. However they are not backward compatible with existing databases (if a sequence or a table is used for id generation).

表3.4 Hibernate JDBC とコネクションプロパティ

プロパティ名 | 意味
--- | ---
hibernate.jdbc.fetch_size | 値が0でない場合、 JDBC フェッチサイズを決定します ( `Statement.setFetchSize()` を呼びます)。
hibernate.jdbc.batch_size | 値が0でない場合、 Hibernate が JDBC2 バッチ更新を使用します。 例： 推奨する値は `5` から `30` の間です。
hibernate.jdbc.batch_versioned_data | Set this property to `true` if your JDBC driver returns correct row counts from `executeBatch()`. It is usually safe to turn this option on. Hibernate will then use batched DML for automatically versioned data. Defaults to `false`. 例 `true` | `false`
hibernate.jdbc.factory_class | カスタム `org.hibernate.jdbc.Batcher` を選びます。ほとんどのアプリケーションに、この設定プロパティは必要ありません。 例 `classname.of.BatcherFactory`
hibernate.jdbc.use_scrollable_resultset | Hibernate による JDBC2 のスクロール可能なリザルトセットの使用を有効にします。このプロパティは、ユーザーによって提供された JDBC コネクションを使用している場合のみ必要で、そうでなければ Hibernate はコネクションメタデータを使用します。 例 `true` | `false`
hibernate.jdbc.use_streams_for_binary | JDBC へ/から `binary` や `serializable` の書き込み/読み込みストリームを使います (システムレベルのプロパティ)。 例 `true` | `false`
hibernate.jdbc.use_get_generated_keys | 挿入の後に自動生成された主キーを取得するための JDBC3 `PreparedStatement.getGeneratedKeys()` の使用を有効にします。これは JDBC3+ ドライバと JRE1.4+ を必要とし、もし Hibernate の識別子ジェネレータに問題が発生するようなら false に設定してください。デフォルトではコネクションメタデータを使いドライバの能力を決定します。 例 `true|false`
hibernate.connection.provider_class | JDBC コネクションを Hibernate に提供する独自の `ConnectionProvider` のクラス名。 例 `classname.of.ConnectionProvider`
hibernate.connection.isolation | JDBC トランザクション分離レベルを設定します。妥当な値を調べるためには `java.sql.Connection` をチェックしてください。しかし使用するデータベースが、すべての分離レベルをサポートしているとは限りません。 例 `1, 2, 4, 8`
hibernate.connection.autocommit | プールされている JDBC コネクションの自動コミットを有効にする（非推奨）。 例 `true` | `false`

hibernate.connection.release_mode

Hibernate がいつ JDBC コネクションをリリースするかを指定します。デフォルトではセッションが明示的にクローズまたは切断されてもコネクションは保持します。アプリケーションサーバーの JTA データソースの場合、すべての JDBC コールの後、強制的にコネクションをリリースするために `after_statement` を使ってください。非 JTA コネクションの場合、各トランザクションが終了したときに `after_transaction` を使い、コネクションをリリースしてください。 `auto` にすると、 JTA や CMT トランザクションの場合、 `after_statement` でクローズし、 JDBC トランザクションの場合、 `after_transaction` でクローズします。

例 `auto` (デフォルト) | `on_close` | `after_transaction` | `after_statement`

This setting only affects `Session`s returned from `SessionFactory.openSession`. For `Session`s obtained through `SessionFactory.getCurrentSession`, the `CurrentSessionContext` implementation configured for use controls the connection release mode for those `Session`s. See 「コンテキスト上のセッション」

hibernate.connection.<propertyName> | JDBC プロパティ <propertyName> を `DriverManager.getConnection()` に渡します。
hibernate.jndi.<propertyName> | プロパティ <propertyName> を JNDI `InitialContextFactory` に渡します。

表3.5 Hibernate キャッシュプロパティ

プロパティ名 | 意味
--- | ---
`hibernate.cache.provider_class` | カスタム `CacheProvider` のクラス名です。 例 `classname.of.CacheProvider`
`hibernate.cache.use_minimal_puts` | 書き込みを最小限にするために、二次キャッシュの操作を最適化します。その代わりに、読み込みがより頻繁に発生するようになります。このセッティングはクラスタキャッシュで役に立ちます。 Hibernate3 ではクラスタキャッシュ実装用にデフォルトでは有効になっています。 例 `true|false`
`hibernate.cache.use_query_cache` | 特定のクエリがキャッシュ可能な場合に、クエリキャッシュを有効にします。 例 `true|false`
`hibernate.cache.use_second_level_cache` | 二次キャッシュを完全に無効にする場合に使います。デフォルトでは有効で、クラスの `<cache>` マッピングで制御します。 例 `true|false`
`hibernate.cache.query_cache_factory` | カスタム `QueryCache` インターフェースのクラス名を指定します。デフォルトでは `StandardQueryCache` になります。 e.g. `classname.of.QueryCache`
`hibernate.cache.region_prefix` | 二次キャッシュの領域名の接頭辞です。 例 `prefix`
`hibernate.cache.use_structured_entries` | 二次キャッシュに格納するデータを、人が理解しやすいフォーマットにします。 例 `true|false`
`hibernate.cache.default_cache_concurrency_strategy` | Setting used to give the name of the default `org.hibernate.annotations.CacheConcurrencyStrategy` to use when either `@Cacheable` or `@Cache` is used. `@Cache(strategy="..")` is used to override this default.

表3.6 Hibernate トランザクションプロパティ

プロパティ名 | 意味
--- | ---
`hibernate.transaction.factory_class` | Hibernate `Transaction` API と一緒に使われる `TransactionFactory` のクラス名です。 （デフォルトでは `JDBCTransactionFactory` です）。 例 `classname.of.TransactionFactory` >
`jta.UserTransaction` | アプリケーションサーバーから JTA `UserTransaction` を取得するために `JTATransactionFactory` に使われる JNDI 名です。 例 `jndi/composite/name`
`hibernate.transaction.manager_lookup_class` | `TransactionManagerLookup` のクラス名です。 JTA 環境において、 JVM レベルのキャッシュを有効にするときか、 hilo ジェネレータが使用されるときに必要です。 例 `classname.of.TransactionManagerLookup`
`hibernate.transaction.flush_before_completion` | If enabled, the session will be automatically flushed during the before completion phase of the transaction. Built-in and automatic session context management is preferred, see 「コンテキスト上のセッション」. 例 `true` | `false`
`hibernate.transaction.auto_close_session` | If enabled, the session will be automatically closed during the after completion phase of the transaction. Built-in and automatic session context management is preferred, see 「コンテキスト上のセッション」. 例 `true` | `false`

表3.7 その他のプロパティ

プロパティ名 | 意味
--- | ---
`hibernate.current_session_context_class` | Supply a custom strategy for the scoping of the "current" `Session`. See 「コンテキスト上のセッション」 for more information about the built-in strategies. 例 `jta` | `thread` | `managed` | `custom.Class`
`hibernate.query.factory_class` | HQL パーサーの実装を選択します。 例 `org.hibernate.hql.ast.ASTQueryTranslatorFactory` or `org.hibernate.hql.classic.ClassicQueryTranslatorFactory`
`hibernate.query.substitutions` | HQL と SQL のトークンをマッピングします。 （例えば、トークンは関数やリテラル名です）。 例 `hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC`
`hibernate.hbm2ddl.auto` | `SessionFactory` を生成したときに、自動的にスキーマ DDL を有効にしデータベースに出力します。 `create-drop` の場合、 `SessionFactory` をクローズしたときに、データベーススキーマをドロップします。 例 `validate` | `update` | `create` | `create-drop`

`hibernate.hbm2ddl.import_files`

Comma-separated names of the optional files containing SQL DML statements executed during the `SessionFactory` creation. This is useful for testing or demoing: by adding INSERT statements for example you can populate your database with a minimal set of data when it is deployed.

File order matters, the statements of a give file are executed before the statements of the following files. These statements are only executed if the schema is created ie if `hibernate.hbm2ddl.auto` is set to `create` or `create-drop`.

e.g. `/humans.sql,/dogs.sql`

`hibernate.bytecode.use_reflection_optimizer` | Enables the use of bytecode manipulation instead of runtime reflection. This is a System-level property and cannot be set in `hibernate.cfg.xml`. Reflection can sometimes be useful when troubleshooting. Hibernate always requires either CGLIB or javassist even if you turn off the optimizer. 例 `true` | `false`
`hibernate.bytecode.provider` | Both javassist or cglib can be used as byte manipulation engines; the default is `javassist`. e.g. `javassist` | `cglib`

### 3.4.1. SQL 方言（Dialect）

`hibernate.dialect` プロパティには、使用するデータベースの正しい `org.hibernate.dialect.Dialect` のサブクラスを、必ず指定すべきです。しかし方言を指定すれば、 Hibernate は上述したプロパティのいくつかについて、より適切なデフォルト値を使います。そうすれば、それらを手作業で設定する手間が省けます。

表3.8 Hibernate SQL Dialects (`hibernate.dialect`)

RDBMS | Dialect
--- | ---
DB2 | `org.hibernate.dialect.DB2Dialect`
DB2 AS/400 | `org.hibernate.dialect.DB2400Dialect`
DB2 OS390 | `org.hibernate.dialect.DB2390Dialect`
PostgreSQL | `org.hibernate.dialect.PostgreSQLDialect`
MySQL5 | `org.hibernate.dialect.MySQL5Dialect`
MySQL5 with InnoDB | `org.hibernate.dialect.MySQL5InnoDBDialect`
MySQL with MyISAM | `org.hibernate.dialect.MySQLMyISAMDialect`
Oracle （いずれのバージョンでも） | `org.hibernate.dialect.OracleDialect`
Oracle 9i | `org.hibernate.dialect.Oracle9iDialect`
Oracle 10g | `org.hibernate.dialect.Oracle10gDialect`
Oracle 11g | `org.hibernate.dialect.Oracle10gDialect`
Sybase | `org.hibernate.dialect.SybaseASE15Dialect`
Sybase Anywhere | `org.hibernate.dialect.SybaseAnywhereDialect`
Microsoft SQL Server 2000 | `org.hibernate.dialect.SQLServerDialect`
Microsoft SQL Server 2005 | `org.hibernate.dialect.SQLServer2005Dialect`
Microsoft SQL Server 2008 | `org.hibernate.dialect.SQLServer2008Dialect`
SAP DB | `org.hibernate.dialect.SAPDBDialect`
Informix | `org.hibernate.dialect.InformixDialect`
HypersonicSQL | `org.hibernate.dialect.HSQLDialect`
H2 Database | `org.hibernate.dialect.H2Dialect`
Ingres | `org.hibernate.dialect.IngresDialect`
Progress | `org.hibernate.dialect.ProgressDialect`
Mckoi SQL | `org.hibernate.dialect.MckoiDialect`
Interbase | `org.hibernate.dialect.InterbaseDialect`
Pointbase | `org.hibernate.dialect.PointbaseDialect`
FrontBase | `org.hibernate.dialect.FrontbaseDialect`
Firebird | `org.hibernate.dialect.FirebirdDialect`

### 3.4.2. 外部結合フェッチ

もしデータベースが ANSI か、 Oracle か Sybase スタイルの外部結合をサポートしている場合、 outer join fetching は、データベースの SQL 発行回数を節約しパフォーマンスを良くします（データベース内でより多くの処理コストが発生します）。外部結合フェッチは、多対一、一対多、多対多、一対一のオブジェクト関連でグループオブジェクトを1つの SQL で `SELECT` します。

`hibernate.max_fetch_depth` プロパティの値を `0` にすると外部結合フェッチを すべて 無効にすることになります。 `1` やそれ以上の値を設定すると、外部結合フェッチが有効になり、一対一と多対一関連が `fetch="join"` としてマッピングされます。

See 「フェッチ戦略」 for more information.

### 3.4.3. バイナリストリーム

Oracle は JDBC ドライバとの間でやりとりされる `byte` 配列のサイズを制限します。 `binary` や `serializable` 型の大きなインスタンスを使いたければ、 `hibernate.jdbc.use_streams_for_binary` を有効にしてください。 ただし これはシステムレベルの設定だけです 。

### 3.4.4. ニ次キャッシュとクエリキャッシュ

The properties prefixed by `hibernate.cache` allow you to use a process or cluster scoped second-level cache system with Hibernate. See the 「第2レベルキャッシュ」 for more information.

### 3.4.5. クエリ言語の置き換え

`hibernate.query.substitutions` を使うことで、新しい Hibernate クエリトークンを定義できます。例：

    hibernate.query.substitutions true=1, false=0

これはトークン `true` と `false` を、生成される SQL において整数リテラルに翻訳します。

    hibernate.query.substitutions toLowercase=LOWER

これは SQL の `LOWER` 関数の名前の付け替えを可能にします。

### 3.4.6. Hibernate 統計

`hibernate.generate_statistics` を有効にした場合、動作しているシステムをチューニングするときに、 `SessionFactory.getStatistics()` を経由して、 Hibernate は便利な統計情報を出力します。 JMX を経由して統計情報を出力することも可能です。 Javadoc の `org.hibernate.stats` パッケージ内のインターフェースにはより多くの情報があります。

## 3.5. ロギング

Hibernate utilizes Simple Logging Facade for Java (SLF4J) in order to log various system events. SLF4J can direct your logging output to several logging frameworks (NOP, Simple, log4j version 1.2, JDK 1.4 logging, JCL or logback) depending on your chosen binding. In order to setup logging you will need `slf4j-api.jar` in your classpath together with the jar file for your preferred binding - `slf4j-log4j12.jar` in the case of Log4J. See the SLF4J documentation for more detail. To use Log4j you will also need to place a `log4j.properties` file in your classpath. An example properties file is distributed with Hibernate in the `src/` directory.

Hibernate のログメッセージに慣れることを強くおすすめします。 Hibernate のログは読みやすく、できる限り詳細になるように努力されています。これは必須のトラブルシューティングデバイスです。以下に重要なログのカテゴリを示します:

表3.9 Hibernate ログカテゴリ

カテゴリ | 機能
--- | ---
`org.hibernate.SQL` | 実行したすべての SQL（DDL）ステートメントをロギングします。
`org.hibernate.type` | すべての JDBC パラメータをロギングします。
`org.hibernate.tool.hbm2ddl` | 実行したすべての SQL（DDL）ステートメントをロギングします。
`org.hibernate.pretty` | session に関連するすべてのエンティティ（最大２０）のフラッシュ時間をロギングします。
`org.hibernate.cache` | すべてのニ次キャッシュの動作をロギングします。
`org.hibernate.transaction` | トランザクションに関連する動作をロギングします。
`org.hibernate.jdbc` | JDBC リソース取得をロギングします。
`org.hibernate.hql.ast.AST` | HQL と SQL の AST のクエリパースをロギングします。
`org.hibernate.secure` | すべての JAAS 分析をロギングします。
`org.hibernate` | すべてをロギングします。（情報が大量になりますが、トラブルシューティングには便利です）

Hibernate でアプリケーションを作成するときは、 `org.hibernate.SQL` カテゴリの `debug` を常に有効にしておいたほうが良いでしょう。代替方法として、 `hibernate.show_sql` プロパティを有効にする方法があります。

## 3.6. `NamingStrategy` を選択

インターフェース `net.sf.hibernate.cfg.NamingStrategy` を使うとデータベースオブジェクトとスキーマ要素のための「命名標準」を指定できます。

Java の識別子からデータベースの識別子を自動生成するためのルールや、マッピングファイルで与えた「論理的な」カラムとテーブル名から「物理的な」テーブルとカラム名を生成するためのルールを用意することができます。この機能は繰り返しの雑音（例えば `TBL_` プリフィックス）を取り除き、マッピングドキュメントの冗長さを減らすことに役立ちます。 Hibernate が使うデフォルトの戦略はかなり最小限に近いものです。

マッピングを追加する前に `Configuration.setNamingStrategy()` を呼ぶことで以下のように異なる戦略を指定することができます：

    SessionFactory sf = new Configuration()

        .setNamingStrategy(ImprovedNamingStrategy.INSTANCE)

        .addFile("Item.hbm.xml")

        .addFile("Bid.hbm.xml")

        .buildSessionFactory();

`org.hibernate.cfg.ImprovedNamingStrategy` は組み込みの戦略です。これはいくつかのアプリケーションにとって有用な開始点となるかもしれません。

## 3.7. Implementing a PersisterClassProvider

You can configure the persister implementation used to persist your entities and collections:

- by default, Hibernate uses persisters that make sense in a relational model and follow Java Persistence's specification

- you can define a `PersisterClassProvider` implementation that provides the persister class used of a given entity or collection

- finally, you can override them on a per entity and collection basis in the mapping using `@Persister` or its XML equivalent

The latter in the list the higher in priority.

You can pass the `PersisterClassProvider` instance to the `Configuration` object.

    SessionFactory sf = new Configuration()

        .setPersisterClassProvider(customPersisterClassProvider)

        .addAnnotatedClass(Order.class)

        .buildSessionFactory();

The persister class provider methods, when returning a non null persister class, override the default Hibernate persisters. The entity name or the collection role are passed to the methods. It is a nice way to centralize the overriding logic of the persisters instead of spreading them on each entity or collection mapping.

## 3.8. XML 設定ファイル

もう1つの方法は `hibernate.cfg.xml` という名前のファイルで十分な設定を指定する方法です。このファイルは `hibernate.properties` ファイルの代わりとなります。もし両方のファイルがあれば、プロパティが置き換えられます。

XML 設定ファイルは初期設定で `CLASSPATH` の root に配置してください。これが例です：

    <?xml version='1.0' encoding='utf-8'?>

    <!DOCTYPE hibernate-configuration PUBLIC

        "-//Hibernate/Hibernate Configuration DTD//EN"

        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

    <hibernate-configuration>

        <!-- a SessionFactory instance listed as /jndi/name -->

        <session-factory

            name="java:hibernate/SessionFactory">

            <!-- properties -->

            <property name="connection.datasource">java:/comp/env/jdbc/MyDB</property>

            <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

            <property name="show_sql">false</property>

            <property name="transaction.factory_class">

                org.hibernate.transaction.JTATransactionFactory

            </property>

            <property name="jta.UserTransaction">java:comp/UserTransaction</property>

            <!-- mapping files -->

            <mapping resource="org/hibernate/auction/Item.hbm.xml"/>

            <mapping resource="org/hibernate/auction/Bid.hbm.xml"/>

            <!-- cache settings -->

            <class-cache class="org.hibernate.auction.Item" usage="read-write"/>

            <class-cache class="org.hibernate.auction.Bid" usage="read-only"/>

            <collection-cache collection="org.hibernate.auction.Item.bids" usage="read-write"/>

        </session-factory>

    </hibernate-configuration>

見てのとおり、この方法の優位性は設定のためのマッピングファイル名を外出しにできることです。 Hibernate キャッシュをチューニングしなければならないのであれば、 `hibernate.cfg.xml` はより便利です。 `hibernate.properties` と `hibernate.cfg.xml` の どちらかを使えることを覚えておいてください。2つは同じもので、違うところといえば XML 構文を使うことの利点だけです。

XML 設定を使うことで、 Hibernate は以下のようにシンプルになります。

    SessionFactory sf = new Configuration().configure().buildSessionFactory();

違う XML 設定ファイルを使うこともできます。

    SessionFactory sf = new Configuration()

        .configure("catdb.cfg.xml")

        .buildSessionFactory();

## 3.9. Java EE Application Server integration

Hibernate は J2EE 構造と統合するポイントをサポートしています:

- コンテナ管理データソース： Hibernate は JNDI が提供し、コンテナが管理する JDBC コネクションを使用できます。通常、 JTA 準拠の `TransactionManager` と `ResourceManager` がトランザクション管理 (CMT)、特に様々なデータソースにまたがる分散トランザクションを扱います。当然プログラムでトランザクション境界を指定できます (BMT)。あるいは、記述したコードのポータビリティを保つために、オプションの Hibernate の `Transaction` API を使いたくなるかもしれません。

- 自動 JNDI バインディング： Hibernate は JNDI が立ち上がった後に `SessionFactory` を生成します。

- JTA セッションバインディング： Hibernate `Session` は自動的に JTA トランザクションのスコープにバインドされます。単純に `SessionFactory` を JNDI から lookup して、現在の `Session` を取得します。 JTA トランザクションが完了したときに、 Hibernateが `Session` をフラッシュし、クローズします。トランザクション境界は、宣言 (CMT) することも、プログラム (BMT/UserTransaction) することも可能です。

- JMX デプロイメント: もし JMX が使用可能なアプリケーションサーバー（例えば JBoss AS） がある場合、 Hibernate を MBean としてデプロイすることを選べます。これは `Configuration` から `SessionFactory` を生成するコードを無くすことができます。コンテナは `HibernateService` を起動し、サービスの依存を理想的に管理します（データソースは Hibernate やその他が起動する前に使用できるようにしなければなりません）。

環境に依存しますが、もしアプリケーションサーバーが "connection containment" の例外を出す場合、設定のオプション `hibernate.connection.aggressive_release` を true にしてください。

### 3.9.1. トランザクション戦略設定

Hibernate `Session` API は、アーキテクチャ内のシステムの管轄であるあらゆるトランザクションに依存しません。もしコネクションプールの JDBC を直接使いたい場合、 JDBC API から トランザクションを呼ぶことができます。もし、 J2EE アプリケーションサーバーで動作させるなら、 Bean 管理トランザクションを使い、必要に応じて `UserTransaction` を JTA API から呼ぶことになるでしょう。

2つ（それ以上）の環境で互換性のあるコードを維持するために、オプションとして根本的なシステムをラッピングする Hibernate `Transaction` API を推奨します。 Hibernate 設定プロパティの `hibernate.transaction.factory_class` を設定することで、ある特定の `Transaction` クラスのインスタンスを持つことができます。

3つの基本的な（既にある）選択を挙げます：

`org.hibernate.transaction.JDBCTransactionFactory`

  データベース (JDBC) トランザクションに委譲します（デフォルト）

`org.hibernate.transaction.JTATransactionFactory`

  もし、このコンテキスト（例えば、 EJB セッション Bean メソッド）で進行中のトランザクションが存在する場合、コンテナ管理トランザクションに委譲します。そうでない場合は、新しいトランザクションが開始されており、 Bean 管理トランザクションが使われます。

`org.hibernate.transaction.CMTTransactionFactory`

  コンテナ管理 JTA トランザクションに委譲します

自分自身のトランザクション戦略（例えば、 CORBA トランザクションサービス）を定義することもできます。

Hibernate のいくつかの機能（例えば、二次キャッシュ、 JTA によるコンテキストセッション等）は管理された環境の中の JTA `TransactionManager` へのアクセスを要求します。 J2EE がひとつのメカニズムに規格化されていないので、アプリケーションサーバーにおいて、 Hibernateが `TransactionManager` のリファレンスを取得する方法を明確にする必要があります。

表3.10 JTA トランザクションマネージャ

Transaction Factory | Application Server
--- | ---
`org.hibernate.transaction.JBossTransactionManagerLookup` | JBoss AS
`org.hibernate.transaction.WeblogicTransactionManagerLookup` | Weblogic
`org.hibernate.transaction.WebSphereTransactionManagerLookup` | WebSphere
`org.hibernate.transaction.WebSphereExtendedJTATransactionLookup` | WebSphere 6
`org.hibernate.transaction.OrionTransactionManagerLookup` | Orion
`org.hibernate.transaction.ResinTransactionManagerLookup` | Resin
`org.hibernate.transaction.JOTMTransactionManagerLookup` | JOTM
`org.hibernate.transaction.JOnASTransactionManagerLookup` | JOnAS
`org.hibernate.transaction.JRun4TransactionManagerLookup` | JRun4
`org.hibernate.transaction.BESTransactionManagerLookup` | Borland ES
`org.hibernate.transaction.JBossTSStandaloneTransactionManagerLookup` | JBoss TS used standalone (ie. outside JBoss AS and a JNDI environment generally). Known to work for `org.jboss.jbossts:jbossjta:4.11.0.Final`

### 3.9.2. `SessionFactory` の JNDI への登録

JNDI に登録した Hibernate `SessionFactory` はファクトリのルックアップと新しい `Session` の作成を簡易化します。これは JNDI に登録された `Datasource` には関連せず、両方とも単に同じ登録を使うことに注意してください。

もし `SessionFactory` を JNDI ネームスペースに登録したい場合、特別な名前（例えば、 `java:hibernate/SessionFactory` ）を `hibernate.session_factory_name` プロパティに使ってください。もしこのプロパティを省略した場合、 `SessionFactory` は JNDI に登録されません。（これは Tomcat のようなデフォルト実装で JNDI が読み取り専用の環境の場合は特に便利です。）

`SessionFactory` を JNDI に登録するとき、 Hibernate は `hibernate.jndi.url` の値を使用し、`hibernate.jndi.class` をイニシャルコンテキストとして具体化します。もし何も設定しない場合は、デフォルトの `InitialContext` を使用します。

`cfg.buildSessionFactory()` をコール後 Hibernate は自動的に `SessionFactory` を JNDI に配置します。 `HibernateService` と一緒に JMX デプロイメントを使わない限り、これはこの呼び出しをアプリケーション内の何らかのスタートアップコード（もしくはユーティリティクラス） に配置しなければならないことを意味します（後で議論します）。

もし JNDI `SessionFactory` を使う場合、 EJB や他のクラスは JNDI ルックアップを使って `SessionFactory` を取得します。

It is recommended that you bind the `SessionFactory` to JNDI in a managed environment and use a `static` singleton otherwise. To shield your application code from these details, we also recommend to hide the actual lookup code for a `SessionFactory` in a helper class, such as `HibernateUtil.getSessionFactory()`. Note that such a class is also a convenient way to startup Hibernate—see chapter 1.

### 3.9.3. JTA による現在のセッションコンテキストマネージメント

The easiest way to handle `Sessions` and transactions is Hibernate's automatic "current" `Session` management. For a discussion of contextual sessions see 「コンテキスト上のセッション」. Using the `"jta"` session context, if there is no Hibernate `Session` associated with the current JTA transaction, one will be started and associated with that JTA transaction the first time you call `sessionFactory.getCurrentSession()`. The `Session`s retrieved via `getCurrentSession()` in the `"jta"` context are set to automatically flush before the transaction completes, close after the transaction completes, and aggressively release JDBC connections after each statement. This allows the `Session`s to be managed by the life cycle of the JTA transaction to which it is associated, keeping user code clean of such management concerns. Your code can either use JTA programmatically through `UserTransaction`, or (recommended for portable code) use the Hibernate `Transaction` API to set transaction boundaries. If you run in an EJB container, declarative transaction demarcation with CMT is preferred.

### 3.9.4. JMX デプロイメント

`SessionFactory` を JNDI から取得するためには `cfg.buildSessionFactory()` 行をどこかで実行していなければなりません。あなたはこれを、 `static` 初期化ブロック内（ `HibernateUtil` のような）か managed service として Hibernate をデプロイするか、どちらかで実行できます。

JBoss AS のような JMX の機能でアプリケーションサーバーにデプロイするために `org.hibernate.jmx.HibernateService` を使って、配置します。実際のデプロイメントと設定はベンダー特有です。ここで例として JBoss 4.0.x 用の `jboss-service.xml` を示します。

    <?xml version="1.0"?>

    <server>

    <mbean code="org.hibernate.jmx.HibernateService"

        name="jboss.jca:service=HibernateFactory,name=HibernateFactory">

        <!-- Required services -->

        <depends>jboss.jca:service=RARDeployer</depends>

        <depends>jboss.jca:service=LocalTxCM,name=HsqlDS</depends>

        <!-- Bind the Hibernate service to JNDI -->

        <attribute name="JndiName">java:/hibernate/SessionFactory</attribute>

        <!-- Datasource settings -->

        <attribute name="Datasource">java:HsqlDS</attribute>

        <attribute name="Dialect">org.hibernate.dialect.HSQLDialect</attribute>

        <!-- Transaction integration -->

        <attribute name="TransactionStrategy">

            org.hibernate.transaction.JTATransactionFactory</attribute>

        <attribute name="TransactionManagerLookupStrategy">

            org.hibernate.transaction.JBossTransactionManagerLookup</attribute>

        <attribute name="FlushBeforeCompletionEnabled">true</attribute>

        <attribute name="AutoCloseSessionEnabled">true</attribute>

        <!-- Fetching options -->

        <attribute name="MaximumFetchDepth">5</attribute>

        <!-- Second-level caching -->

        <attribute name="SecondLevelCacheEnabled">true</attribute>

        <attribute name="CacheProviderClass">org.hibernate.cache.EhCacheProvider</attribute>

        <attribute name="QueryCacheEnabled">true</attribute>

        <!-- Logging -->

        <attribute name="ShowSqlEnabled">true</attribute>

        <!-- Mapping files -->

        <attribute name="MapResources">auction/Item.hbm.xml,auction/Category.hbm.xml</attribute>

    </mbean>

    </server>

このファイルは `META-INF` ディレクトリに配置され、 JAR ファイルを拡張した `.sar` (service archive) でパッケージ化されます。同様に Hibernate パッケージも必要です。また、 Hibernate はサードパーティのライブラリも要求します。コンパイルした永続化クラスとそのマッピングファイルも同様にアーカイブ（.sarファイル）に入れます。エンタープライズ Bean （通常はセッション Bean ）は自身の JAR ファイルを保持しますが、1回で（ホット）デプロイ可能なユニットのためにメインサービスアーカイブとしてこの EJB JAR ファイルを含めることができます。 JBoss AS のドキュメントに JXM サービスと EJB デプロイメントのより多くの情報があります。

## 第4章 永続クラス

Persistent classes are classes in an application that implement the entities of the business problem (e.g. Customer and Order in an E-commerce application). The term "persistent" here means that the classes are able to be persisted, not that they are in the persistent state (see 「Hibernate におけるオブジェクトの状態」 for discussion).

Hibernate works best if these classes follow some simple rules, also known as the Plain Old Java Object (POJO) programming model. However, none of these rules are hard requirements. Indeed, Hibernate assumes very little about the nature of your persistent objects. You can express a domain model in other ways (using trees of `java.util.Map` instances, for example).

## 4.1. 単純な POJO の例

例4.1 Simple POJO representing a cat

    package eg;

    import java.util.Set;

    import java.util.Date;

    public class Cat {

    private Long id; // identifier

    private Date birthdate;

    private Color color;

    private char sex;

    private float weight;

        private int litterId;

        private Cat mother;

        private Set kittens = new HashSet();

        private void setId(Long id) {

            this.id=id;

        }

        public Long getId() {

            return id;

        }

        void setBirthdate(Date date) {

            birthdate = date;

        }

        public Date getBirthdate() {

            return birthdate;

        }

        void setWeight(float weight) {

            this.weight = weight;

        }

        public float getWeight() {

            return weight;

        }

        public Color getColor() {

            return color;

        }

        void setColor(Color color) {

            this.color = color;

        }

        void setSex(char sex) {

            this.sex=sex;

        }

        public char getSex() {

            return sex;

        }

        void setLitterId(int id) {

            this.litterId = id;

        }

        public int getLitterId() {

            return litterId;

        }

        void setMother(Cat mother) {

            this.mother = mother;

        }

        public Cat getMother() {

            return mother;

        }

        void setKittens(Set kittens) {

            this.kittens = kittens;

        }

        public Set getKittens() {

            return kittens;

        }

        // addKitten not needed by Hibernate

        public void addKitten(Cat kitten) {

            kitten.setMother(this);

        kitten.setLitterId( kittens.size() );

            kittens.add(kitten);

        }

    }

The four main rules of persistent classes are explored in more detail in the following sections.

### 4.1.1. 引数のないコンストラクタを実装する

`Cat` has a no-argument constructor. All persistent classes must have a default constructor (which can be non-public) so that Hibernate can instantiate them using ``java.lang.reflect.Constructor`.newInstance()`. It is recommended that this constructor be defined with at least package visibility in order for runtime proxy generation to work properly.

### 4.1.2. Provide an identifier property

## 注意

Historically this was considered option. While still not (yet) enforced, this should be considered a deprecated feature as it will be completely required to provide a identifier property in an upcoming release.

`Cat` has a property named `id`. This property maps to the primary key column(s) of the underlying database table. The type of the identifier property can be any "basic" type (see ???). See 「複合識別子としてのコンポーネント」 for information on mapping composite (multi-column) identifiers.

## 注意

Identifiers do not necessarily need to identify column(s) in the database physically defined as a primary key. They should just identify columns that can be used to uniquely identify rows in the underlying table.

永続クラスには、一貫した名前の識別子プロパティを定義することをお勧めします。さらに null 値を取れる(つまりプリミティブではない)型を使った方がよいでしょう。

### 4.1.3. Prefer non-final classes (semi-optional)

A central feature of Hibernate, proxies (lazy loading), depends upon the persistent class being either non-final, or the implementation of an interface that declares all public methods. You can persist `final` classes that do not implement an interface with Hibernate; you will not, however, be able to use proxies for lazy association fetching which will ultimately limit your options for performance tuning. To persist a `final` class which does not implement a "full" interface you must disable proxy generation. See 例4.2「Disabling proxies in hbm.xml」 and 例4.3「Disabling proxies in annotations」.

例4.2 Disabling proxies in `hbm.xml`

    <class name="Cat" lazy="false"...>...</class>

例4.3 Disabling proxies in annotations

    @Entity @Proxy(lazy=false) public class Cat { ... }

If the `final` class does implement a proper interface, you could alternatively tell Hibernate to use the interface instead when generating the proxies. See 例4.4「Proxying an interface in hbm.xml」 and 例4.5「Proxying an interface in annotations」.

例4.4 Proxying an interface in `hbm.xml`

    <class name="Cat" proxy="ICat"...>...</class>

例4.5 Proxying an interface in annotations

    @Entity @Proxy(proxyClass=ICat.class) public class Cat implements ICat { ... }

You should also avoid declaring `public final` methods as this will again limit the ability to generate proxies from this class. If you want to use a class with `public final` methods, you must explicitly disable proxying. Again, see 例4.2「Disabling proxies in hbm.xml」 and 例4.3「Disabling proxies in annotations」.

### 4.1.4. 永続フィールドに対するアクセサとミューテータを定義する（オプション）

`Cat` declares accessor methods for all its persistent fields. Many other ORM tools directly persist instance variables. It is better to provide an indirection between the relational schema and internal data structures of the class. By default, Hibernate persists JavaBeans style properties and recognizes method names of the form `getFoo`, `isFoo` and `setFoo`. If required, you can switch to direct field access for particular properties.

Properties need not be declared public. Hibernate can persist a property declared with `package`, `protected` or `private` visibility as well.

## 4.2. 継承の実装

サブクラスも1番目と2番目のルールを守らなければなりません。サブクラスはスーパークラス `Cat` から識別子プロパティを継承します。

    package eg;

    public class DomesticCat extends Cat {

            private String name;

            public String getName() {

                    return name;

            }

            protected void setName(String name) {

                    this.name=name;

            }

    }

## 4.3. `equals()` と `hashCode()`の実装

以下の条件の場合、 `equals()` と `hashCode()` メソッドをオーバーライドしなければなりません、

- 永続クラスのインスタンスを `Set` に置く場合。 （これは多値の関連を表現するおすすめの方法です） そして同時に

- 分離インスタンスをセッションへ再追加する場合。

Hibernate は、永続 ID （データベースの行）と、特定のセッションスコープ内に限定ですが Java ID とが等価であることを保証します。ですから異なるセッションで検索したインスタンスを組み合わせる場合、 `Set` に意味のあるセマンティクスを持たせようと思っているならすぐに `equals()` と `hashCode()` を実装しなければなりません。

最も明白な方法は、両方のオブジェクトの識別子の値の比較によって `equals()`と `hashCode()` を実装する方法です。値が同じなら、両者はデータベースの同じ行でなければならないため等しくなります。 （両者が `Set` に追加されても、 `Set` には1個の要素しかないことになります） 残念なことに、生成された識別子にはこのアプローチを使うことができません。 Hibernate は永続化されたオブジェクトへ識別子の値を代入するだけであり、新しく作成されたインスタンスはどのような識別子の値も持っていません。さらに、インスタンスがセーブされておらず、現在 `Set` の中にあれば、セーブするとオブジェクトへ識別子の値を代入することになります。もし `equals()` と `hashCode()` が識別子の値に基づいているなら、ハッシュコードが変更されると `Set` の規約が破られます。この問題についての完全な議論は、 Hibernate のウェブサイトを見てください。これは Hibernate の問題ではなく、オブジェクトの同一性と等価性についての、通常の Java のセマンティクスであることに注意してください。

ビジネスキーの等価性 を使って、 `equals()` と `hashCode()` を実装することをお勧めします。ビジネスキーの等価性とは、 `equals()` メソッドが、ビジネスキー、つまり現実の世界においてインスタンスを特定するキー（自然 候補キー） を形成するプロパティだけを比較することを意味します。

    public class Cat {

        ...

        public boolean equals(Object other) {

            if (this == other) return true;

            if ( !(other instanceof Cat) ) return false;

            final Cat cat = (Cat) other;

            if ( !cat.getLitterId().equals( getLitterId() ) ) return false;

            if ( !cat.getMother().equals( getMother() ) ) return false;

            return true;

        }

        public int hashCode() {

            int result;

            result = getMother().hashCode();

            result = 29 * result + getLitterId();

            return result;

        }

    }

A business key does not have to be as solid as a database primary key candidate (see 「オブジェクト識別子を考える」). Immutable or unique properties are usually good candidates for a business key.

## 4.4. 動的モデル

## 注意

The following features are currently considered experimental and may change in the near future.

永続エンティティは、必ずしも実行時に POJO クラスや JavaBean オブジェクトで表現する必要はありません。 Hibernate は（実行時に `Map` の `Map` を使う）動的モデルと、 DOM4J ツリーとしてのエンティティの表現もサポートします。このアプローチを使うと永続クラスを書かず、マッピングファイルだけを書くことになります。

By default, Hibernate works in normal POJO mode. You can set a default entity representation mode for a particular `SessionFactory` using the `default_entity_mode` configuration option (see 表3.3「Hibernate 設定プロパティ」).

以下の例では `Map` を使った表現を紹介します。まずマッピングファイルで、クラス名の代わりに（またはそれに加えて） `entity-name` を定義しなければなりません：

    <hibernate-mapping>

        <class entity-name="Customer">

            <id name="id"

                type="long"

                column="ID">

                <generator class="sequence"/>

            </id>

            <property name="name"

                column="NAME"

                type="string"/>

            <property name="address"

                column="ADDRESS"

                type="string"/>

            <many-to-one name="organization"

                column="ORGANIZATION_ID"

                class="Organization"/>

            <bag name="orders"

                inverse="true"

                lazy="false"

                cascade="all">

                <key column="CUSTOMER_ID"/>

                <one-to-many class="Order"/>

            </bag>

        </class>

    </hibernate-mapping>

関連がターゲットのクラス名を使って定義していたとしても、関連のターゲット型も POJO ではなく動的なエンティティでも構わないことに注意してください。

`SessionFactory` に対してデフォルトのエンティティモードを `dynamic-map` に設定した後、実行時に `Map` の `Map` を使うことができます：

    Session s = openSession();

    Transaction tx = s.beginTransaction();

    // Create a customer

    Map david = new HashMap();

    david.put("name", "David");

    // Create an organization

    Map foobar = new HashMap();

    foobar.put("name", "Foobar Inc.");

    // Link both

    david.put("organization", foobar);

    // Save both

    s.save("Customer", david);

    s.save("Organization", foobar);

    tx.commit();

    s.close();

動的なマッピングの利点は、エンティティクラスの実装を必要としないため、プロトタイピングに要するターンアラウンドタイムが早いということです。しかしコンパイル時の型チェックがないので、実行時に非常に多くの例外処理を扱わなければならないでしょう。 Hibernate マッピングのおかげで、データベーススキーマは容易に正規化でき、健全になり、後で適切なドメインモデルの実装を追加することが可能になります。

エンティティ表現モードは `Session` ごとに設定することも可能です。

    Session dynamicSession = pojoSession.getSession(EntityMode.MAP);

    // Create a customer

    Map david = new HashMap();

    david.put("name", "David");

    dynamicSession.save("Customer", david);

    ...

    dynamicSession.flush();

    dynamicSession.close()

    ...

    // Continue on pojoSession

`EntityMode` を使った `getSession()` の呼び出しは `SessionFactory` ではなく `Session` APIにあることに注意してください。その方法では、新しい `Session` は、ベースとなる JDBC コネクション、トランザクション、その他のコンテキスト情報を共有します。これは2番目の `Session` では `flush()` と `close()` を呼ぶ必要がないということ、そのためトランザクションとコネクションの管理を1番目の作業単位(Unit of Work)に任せることができるということです。

More information about the XML representation capabilities can be found in 20章XML マッピング.

## 4.5. Tuplizer

`org.hibernate.tuple.Tuplizer` and its sub-interfaces are responsible for managing a particular representation of a piece of data given that representation's `org.hibernate.EntityMode`. If a given piece of data is thought of as a data structure, then a tuplizer is the thing that knows how to create such a data structure, how to extract values from such a data structure and how to inject values into such a data structure. For example, for the POJO entity mode, the corresponding tuplizer knows how create the POJO through its constructor. It also knows how to access the POJO properties using the defined property accessors.

There are two (high-level) types of Tuplizers:

- `org.hibernate.tuple.entity.EntityTuplizer` which is responsible for managing the above mentioned contracts in regards to entities

- `org.hibernate.tuple.component.ComponentTuplizer` which does the same for components

Users can also plug in their own tuplizers. Perhaps you require that `java.util.Map` implementation other than `java.util.HashMap` be used while in the dynamic-map entity-mode. Or perhaps you need to define a different proxy generation strategy than the one used by default. Both would be achieved by defining a custom tuplizer implementation. Tuplizer definitions are attached to the entity or component mapping they are meant to manage. Going back to the example of our `Customer` entity, 例4.6「Specify custom tuplizers in annotations」 shows how to specify a custom `org.hibernate.tuple.entity.EntityTuplizer` using annotations while 例4.7「Specify custom tuplizers in hbm.xml」 shows how to do the same in `hbm.xml`

例4.6 Specify custom tuplizers in annotations

    @Entity

    @Tuplizer(impl = DynamicEntityTuplizer.class)

    public interface Cuisine {

        @Id

        @GeneratedValue

        public Long getId();

        public void setId(Long id);

        public String getName();

        public void setName(String name);

        @Tuplizer(impl = DynamicComponentTuplizer.class)

        public Country getCountry();

        public void setCountry(Country country);

    }

例4.7 Specify custom tuplizers in `hbm.xml`

    <hibernate-mapping>

        <class entity-name="Customer">

            <!--

                Override the dynamic-map entity-mode

                tuplizer for the customer entity

            -->

            <tuplizer entity-mode="dynamic-map"

                    class="CustomMapTuplizerImpl"/>

            <id name="id" type="long" column="ID">

                <generator class="sequence"/>

            </id>

            <!-- other properties -->

            ...

        </class>

    </hibernate-mapping>

## 4.6. EntityNameResolvers

`org.hibernate.EntityNameResolver` is a contract for resolving the entity name of a given entity instance. The interface defines a single method `resolveEntityName` which is passed the entity instance and is expected to return the appropriate entity name (null is allowed and would indicate that the resolver does not know how to resolve the entity name of the given entity instance). Generally speaking, an `org.hibernate.EntityNameResolver` is going to be most useful in the case of dynamic models. One example might be using proxied interfaces as your domain model. The hibernate test suite has an example of this exact style of usage under the org.hibernate.test.dynamicentity.tuplizer2. Here is some of the code from that package for illustration.

    /**

     * A very trivial JDK Proxy InvocationHandler implementation where we proxy an

     * interface as the domain model and simply store persistent state in an internal

     * Map.  This is an extremely trivial example meant only for illustration.

     */

    public final class DataProxyHandler implements InvocationHandler {

            private String entityName;

            private HashMap data = new HashMap();

            public DataProxyHandler(String entityName, Serializable id) {

                    this.entityName = entityName;

                    data.put( "Id", id );

            }

            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                    String methodName = method.getName();

                    if ( methodName.startsWith( "set" ) ) {

                            String propertyName = methodName.substring( 3 );

                            data.put( propertyName, args[0] );

                    }

                    else if ( methodName.startsWith( "get" ) ) {

                            String propertyName = methodName.substring( 3 );

                            return data.get( propertyName );

                    }

                    else if ( "toString".equals( methodName ) ) {

                            return entityName + "#" + data.get( "Id" );

                    }

                    else if ( "hashCode".equals( methodName ) ) {

                            return new Integer( this.hashCode() );

                    }

                    return null;

            }

            public String getEntityName() {

                    return entityName;

            }

            public HashMap getData() {

                    return data;

            }

    }

    public class ProxyHelper {

        public static String extractEntityName(Object object) {

            // Our custom java.lang.reflect.Proxy instances actually bundle

            // their appropriate entity name, so we simply extract it from there

            // if this represents one of our proxies; otherwise, we return null

            if ( Proxy.isProxyClass( object.getClass() ) ) {

                InvocationHandler handler = Proxy.getInvocationHandler( object );

                if ( DataProxyHandler.class.isAssignableFrom( handler.getClass() ) ) {

                    DataProxyHandler myHandler = ( DataProxyHandler ) handler;

                    return myHandler.getEntityName();

                }

            }

            return null;

        }

        // various other utility methods ....

    }

    /**

     * The EntityNameResolver implementation.

     *

     * IMPL NOTE : An EntityNameResolver really defines a strategy for how entity names

     * should be resolved.  Since this particular impl can handle resolution for all of our

     * entities we want to take advantage of the fact that SessionFactoryImpl keeps these

     * in a Set so that we only ever have one instance registered.  Why?  Well, when it

     * comes time to resolve an entity name, Hibernate must iterate over all the registered

     * resolvers.  So keeping that number down helps that process be as speedy as possible.

     * Hence the equals and hashCode implementations as is

     */

    public class MyEntityNameResolver implements EntityNameResolver {

        public static final MyEntityNameResolver INSTANCE = new MyEntityNameResolver();

        public String resolveEntityName(Object entity) {

            return ProxyHelper.extractEntityName( entity );

        }

        public boolean equals(Object obj) {

            return getClass().equals( obj.getClass() );

        }

        public int hashCode() {

            return getClass().hashCode();

        }

    }

    public class MyEntityTuplizer extends PojoEntityTuplizer {

            public MyEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) {

                    super( entityMetamodel, mappedEntity );

            }

            public EntityNameResolver[] getEntityNameResolvers() {

                    return new EntityNameResolver[] { MyEntityNameResolver.INSTANCE };

            }

        public String determineConcreteSubclassEntityName(Object entityInstance, SessionFactoryImplementor factory) {

            String entityName = ProxyHelper.extractEntityName( entityInstance );

            if ( entityName == null ) {

                entityName = super.determineConcreteSubclassEntityName( entityInstance, factory );

            }

            return entityName;

        }

        ...

In order to register an `org.hibernate.EntityNameResolver` users must either:

1. Implement a custom tuplizer (see 「Tuplizer」), implementing the `getEntityNameResolvers` method

2. Register it with the `org.hibernate.impl.SessionFactoryImpl` (which is the implementation class for `org.hibernate.SessionFactory`) using the `registerEntityNameResolver` method.

## 第5章 基本的な O/R マッピング

## 5.1. マッピング定義

Object/relational mappings can be defined in three approaches:

- using Java 5 annotations (via the Java Persistence 2 annotations)

- using JPA 2 XML deployment descriptors (described in chapter XXX)

- using the Hibernate legacy XML files approach known as hbm.xml

Annotations are split in two categories, the logical mapping annotations (describing the object model, the association between two entities etc.) and the physical mapping annotations (describing the physical schema, tables, columns, indexes, etc). We will mix annotations from both categories in the following code examples.

JPA annotations are in the `javax.persistence.*` package. Hibernate specific extensions are in `org.hibernate.annotations.*`. You favorite IDE can auto-complete annotations and their attributes for you (even without a specific "JPA" plugin, since JPA annotations are plain Java 5 annotations).

Here is an example of mapping

    package eg;

    @Entity

    @Table(name="cats") @Inheritance(strategy=SINGLE_TABLE)

    @DiscriminatorValue("C") @DiscriminatorColumn(name="subclass", discriminatorType=CHAR)

    public class Cat {

       @Id @GeneratedValue

       public Integer getId() { return id; }

       public void setId(Integer id) { this.id = id; }

       private Integer id;

       public BigDecimal getWeight() { return weight; }

       public void setWeight(BigDecimal weight) { this.weight = weight; }

       private BigDecimal weight;

       @Temporal(DATE) @NotNull @Column(updatable=false)

       public Date getBirthdate() { return birthdate; }

       public void setBirthdate(Date birthdate) { this.birthdate = birthdate; }

       private Date birthdate;

       @org.hibernate.annotations.Type(type="eg.types.ColorUserType")

       @NotNull @Column(updatable=false)

       public ColorType getColor() { return color; }

       public void setColor(ColorType color) { this.color = color; }

       private ColorType color;

       @NotNull @Column(updatable=false)

       public String getSex() { return sex; }

       public void setSex(String sex) { this.sex = sex; }

       private String sex;

       @NotNull @Column(updatable=false)

       public Integer getLitterId() { return litterId; }

       public void setLitterId(Integer litterId) { this.litterId = litterId; }

       private Integer litterId;

       @ManyToOne @JoinColumn(name="mother_id", updatable=false)

       public Cat getMother() { return mother; }

       public void setMother(Cat mother) { this.mother = mother; }

       private Cat mother;

       @OneToMany(mappedBy="mother") @OrderBy("litterId")

       public Set<Cat> getKittens() { return kittens; }

       public void setKittens(Set<Cat> kittens) { this.kittens = kittens; }

       private Set<Cat> kittens = new HashSet<Cat>();

    }

    @Entity @DiscriminatorValue("D")

    public class DomesticCat extends Cat {

       public String getName() { return name; }

       public void setName(String name) { this.name = name }

       private String name;

    }

    @Entity

    public class Dog { ... }

The legacy hbm.xml approach uses an XML schema designed to be readable and hand-editable. The mapping language is Java-centric, meaning that mappings are constructed around persistent class declarations and not table declarations.

多くの Hibernate ユーザーは XML マッピングの記述を手作業で行いますが、 XDoclet, Middlegen, AndroMDA というようなマッピングドキュメントを生成するツールがいくつか存在することを覚えておいてください。

サンプルのマッピングから始めましょう：

    <?xml version="1.0"?>

    <!DOCTYPE hibernate-mapping PUBLIC

          "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

              "http://www.hibernate.org/dtd/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>

We will now discuss the concepts of the mapping documents (both annotations and XML). We will only describe, however, the document elements and attributes that are used by Hibernate at runtime. The mapping document also contains some extra optional attributes and elements that affect the database schemas exported by the schema export tool (for example, the `not-null` attribute).

### 5.1.1. Entity

An entity is a regular Java object (aka POJO) which will be persisted by Hibernate.

To mark an object as an entity in annotations, use the `@Entity` annotation.

    @Entity

    public class Flight implements Serializable {

        Long id;

        @Id

        public Long getId() { return id; }

        public void setId(Long id) { this.id = id; }

    }

That's pretty much it, the rest is optional. There are however any options to tweak your entity mapping, let's explore them.

`@Table` lets you define the table the entity will be persisted into. If undefined, the table name is the unqualified class name of the entity. You can also optionally define the catalog, the schema as well as unique constraints on the table.

    @Entity

    @Table(name="TBL_FLIGHT",

           schema="AIR_COMMAND",

           uniqueConstraints=

               @UniqueConstraint(

                   name="flight_number",

                   columnNames={"comp_prefix", "flight_number"} ) )

    public class Flight implements Serializable {

        @Column(name="comp_prefix")

        public String getCompagnyPrefix() { return companyPrefix; }

        @Column(name="flight_number")

        public String getNumber() { return number; }

    }

The constraint name is optional (generated if left undefined). The column names composing the constraint correspond to the column names as defined before the Hibernate `NamingStrategy` is applied.

`@Entity.name` lets you define the shortcut name of the entity you can used in JP-QL and HQL queries. It defaults to the unqualified class name of the class.

Hibernate goes beyond the JPA specification and provide additional configurations. Some of them are hosted on `@org.hibernate.annotations.Entity`:

- `dynamicInsert` / `dynamicUpdate` (defaults to false): specifies that `INSERT` / `UPDATE` SQL should be generated at runtime and contain only the columns whose values are not null. The `dynamic-update` and `dynamic-insert` settings are not inherited by subclasses. Although these settings can increase performance in some cases, they can actually decrease performance in others.

- `selectBeforeUpdate` (defaults to false): specifies that Hibernate should never perform an SQL `UPDATE` unless it is certain that an object is actually modified. Only when a transient object has been associated with a new session using `update()`, will Hibernate perform an extra SQL `SELECT` to determine if an `UPDATE` is actually required. Use of `select-before-update` will usually decrease performance. It is useful to prevent a database update trigger being called unnecessarily if you reattach a graph of detached instances to a `Session`.

- `polymorphisms` (defaults to `IMPLICIT`): determines whether implicit or explicit query polymorphisms is used. Implicit polymorphisms means that instances of the class will be returned by a query that names any superclass or implemented interface or class, and that instances of any subclass of the class will be returned by a query that names the class itself. Explicit polymorphisms means that class instances will be returned only by queries that explicitly name that class. Queries that name the class will return only instances of subclasses mapped. For most purposes, the default `polymorphisms=IMPLICIT` is appropriate. Explicit polymorphisms is useful when two different classes are mapped to the same table This allows a "lightweight" class that contains a subset of the table columns.

- `persister`: specifies a custom `ClassPersister`. The `persister` attribute lets you customize the persistence strategy used for the class. You can, for example, specify your own subclass of `org.hibernate.persister.EntityPersister`, or you can even provide a completely new implementation of the interface `org.hibernate.persister.ClassPersister` that implements, for example, persistence via stored procedure calls, serialization to flat files or LDAP. See `org.hibernate.test.CustomPersister` for a simple example of "persistence" to a `Hashtable`.

- `optimisticLock` (defaults to `VERSION`): determines the optimistic locking strategy. If you enable `dynamicUpdate`, you will have a choice of optimistic locking strategies:

  - `version` バージョン/タイムスタンプカラムをチェックします。

  - `all` すべてのカラムをチェックします。

  - `dirty` 変更したカラムをチェックし、同時更新できるようにします。

  - `none` 楽観ロックを使用しません。

  Hibernate で楽観的ロック戦略を使うなら、バージョン/タイムスタンプカラムを使うことを 非常に 強くお勧めします。楽観的ロックはパフォーマンスの観点からも最適であり、さらに分離インスタンスへの修正 （つまり `Session.marge()` が使われるとき） を正確に扱うことのできる唯一の戦略でもあります。

## ティップ

Be sure to import `@javax.persistence.Entity` to mark a class as an entity. It's a common mistake to import `@org.hibernate.annotations.Entity` by accident.

Some entities are not mutable. They cannot be updated or deleted by the application. This allows Hibernate to make some minor performance optimizations.. Use the `@Immutable` annotation.

You can also alter how Hibernate deals with lazy initialization for this class. On `@Proxy`, use `lazy`=false to disable lazy fetching (not recommended). You can also specify an interface to use for lazy initializing proxies (defaults to the class itself): use `proxyClass` on `@Proxy`. Hibernate will initially return proxies (Javassist or CGLIB) that implement the named interface. The persistent object will load when a method of the proxy is invoked. See "Initializing collections and proxies" below.

`@BatchSize` specifies a "batch size" for fetching instances of this class by identifier. Not yet loaded instances are loaded batch-size at a time (default 1).

You can specific an arbitrary SQL WHERE condition to be used when retrieving objects of this class. Use `@Where` for that.

In the same vein, `@Check` lets you define an SQL expression used to generate a multi-row check constraint for automatic schema generation.

There is no difference between a view and a base table for a Hibernate mapping. This is transparent at the database level, although some DBMS do not support views properly, especially with updates. Sometimes you want to use a view, but you cannot create one in the database (i.e. with a legacy schema). In this case, you can map an immutable and read-only entity to a given SQL subselect expression using `@org.hibernate.annotations.Subselect`:

    @Entity

    @Subselect("select item.name, max(bid.amount), count(*) "

            + "from item "

            + "join bid on bid.item_id = item.id "

            + "group by item.name")

    @Synchronize( {"item", "bid"} ) //tables impacted

    public class Summary {

        @Id

        public String getId() { return id; }

        ...

    }

テーブルをこのエンティティと同期するように定義してください。オートフラッシュが確実に起こるように、また導出エンティティに対するクエリが古いデータを返さないようにするためです。 `<subselect>` は属性とネストしたマッピング属性のどちらでも利用できます。

We will now explore the same options using the hbm.xml structure. You can declare a persistent class using the `class` element. For example:

    <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="(16)true|false"
            entity(17)-name="EntityName"
            check=(18)"arbitrary sql check condition"
            rowid=(19)"rowid"
            subsel(20)ect="SQL expression"
            abstra(21)ct="true|false"
            node="element-name"
    />

| `name` (オプション)：永続クラス（またはインターフェース）の完全修飾 Java クラス名。もしこの属性が欠落している場合、 POJO ではないエンティティに対するマッピングとして扱われます。
| `table` (オプション - デフォルトは修飾されていないクラス名)：データベーステーブルの名前。
| `discriminator-value` (オプション - デフォルトはクラス名)： ポリモーフィックな振る舞いに使われる個々のサブクラスを識別するための値。値は `null` か `not null` のいずれかを取ります。
| `mutable` (オプション、デフォルトは `true` )： そのクラスのインスタンスが更新可能（または不可能）であることを指定します。
| `schema` (オプション): ルートの `<hibernate-mapping>` 要素で指定したスキーマ名をオーバーライドします。
| `catalog` (オプション): ルートの `<hibernate-mapping>` 要素で指定したカタログ名をオーバーライドします。
| `proxy` （オプション）：遅延初期化プロキシに使うインターフェースを指定します。永続化するクラス名そのものを指定することも可能です。
| `dynamic-update` （オプション、 デフォルトは `false` ）：値が変更されたカラムだけを含む SQL の `UPDATE` 文を、実行時に生成することを指定します。
| `dynamic-insert` （オプション, デフォルトは `false` ）：値が null ではないカラムだけを含む SQL の `INSERT` 文を、実行時に生成することを指定します。
| `select-before-update` (オプション、デフォルトは `false`): オブジェクトが変更されたのが確実でないならば、 Hibernate が SQL の `UPDATE` を 決して実行しない ことを指定します。ある特定の場合(実際的には、一時オブジェクトが `update()` を使い、新しいセッションと関連付けられた時だけ)、 `UPDATE` が実際に必要かどうかを決定するために、 Hibernate が余分な SQL の `SELECT` 文を実行することを意味します。
| `polymorphisms` (optional - defaults to `implicit`): determines whether implicit or explicit query polymorphisms is used.
| `where` （オプション）： このクラスのオブジェクトを検索するときに使用する、任意の SQL の `WHERE` 条件を指定します。
| `persister` （オプション）：カスタム `ClassPersister` を指定します。
| `batch-size` （オプション、デフォルトは `1` ）： 識別子でこのクラスのインスタンスを復元するときの「バッチサイズ」を指定します。
| `optimistic-lock` （オプション、デフォルトは `version` ）： 楽観ロック戦略を決定します。
(16) | `lazy` （オプション）： `lazy="false"` と設定することで、遅延フェッチができなくなります。
(17) | `entity-name` (optional - defaults to the class name): Hibernate3 allows a class to be mapped multiple times, potentially to different tables. It also allows entity mappings that are represented by Maps or XML at the Java level. In these cases, you should provide an explicit arbitrary name for the entity. See 「動的モデル」 and 20章XML マッピング for more information.
(18) | `check` （オプション）：自動的にスキーマを生成するために、複数行の check 制約を生成する SQL 式。
(19) | `rowid` （オプション）： Hibernate は、それをサポートしているデータベースで ROWID と 呼ばれるものを使うことができます。例えば Oracle を使っているとき、このオプションに `rowid` を設定すれば、 Hiberante は update を高速化するために `rowid` という特別なカラムを使うことができます。 ROWID は詳細な実装であり、保存されたタプルの物理的な位置を表しています。
(20) | `subselect` (optional): maps an immutable and read-only entity to a database subselect. This is useful if you want to have a view instead of a base table. See below for more information.
(21) | `abstract` （オプション）： `<union-subclass>` 階層内の抽象スーパークラスにマークするために使います。

永続クラスの名前にインターフェースを指定してもまったく問題ありません。そのときは `<subclass>` 要素を使って、そのインターフェースを実装するクラスを定義してください。 static な内部クラスでも永続化できます。そのときは標準形式、例えば `eg.Foo$Bar` を使ってクラス名を指定してください。

Here is how to do a virtual view (subselect) in XML:

    <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>

The `<subselect>` is available both as an attribute and a nested mapping element.

### 5.1.2. Identifiers

Mapped classes must declare the primary key column of the database table. Most classes will also have a JavaBeans-style property holding the unique identifier of an instance.

Mark the identifier property with `@Id`.

    @Entity

    public class Person {

       @Id Integer getId() { ... }

       ...

    }

In hbm.xml, use the `<id>` element which defines the mapping from that property to the primary key column.

    <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>

| `name`（オプション）：識別子プロパティの名前。
| `type`（オプション）： Hibernate の型を示す名前。
| `column`（オプション - デフォルトはプロパティ名）： 主キーカラムの名前。
| `unsaved-value`（オプション - デフォルトの値は sensible ）： インスタンスが新しくインスタンス化された （セーブされていない）ことを示す、識別子プロパティの値。以前の Session でセーブまたはロードされた分離インスタンスと区別するために使います。
| `access` (オプション - デフォルトは `property` ): Hibernate がプロパティの値にアクセスするために使用すべき戦略。

`name` 属性がなければ、クラスには識別子プロパティがないものとみなされます。

The `unsaved-value` attribute is almost never needed in Hibernate3 and indeed has no corresponding element in annotations.

You can also declare the identifier as a composite identifier. This allows access to legacy data with composite keys. Its use is strongly discouraged for anything else.

#### 5.1.2.1. Composite identifier

You can define a composite primary key through several syntaxes:

- use a component type to represent the identifier and map it as a property in the entity: you then annotated the property as `@EmbeddedId`. The component type has to be `Serializable`.

- map multiple properties as `@Id` properties: the identifier type is then the entity class itself and needs to be `Serializable`. This approach is unfortunately not standard and only supported by Hibernate.

- map multiple properties as `@Id` properties and declare an external class to be the identifier type. This class, which needs to be `Serializable`, is declared on the entity via the `@IdClass` annotation. The identifier type must contain the same properties as the identifier properties of the entity: each property name must be the same, its type must be the same as well if the entity property is of a basic type, its type must be the type of the primary key of the associated entity if the entity property is an association (either a `@OneToOne` or a `@ManyToOne`).

As you can see the last case is far from obvious. It has been inherited from the dark ages of EJB 2 for backward compatibilities and we recommend you not to use it (for simplicity sake).

Let's explore all three cases using examples.

##### 5.1.2.1.1. id as a property using a component type

Here is a simple example of `@EmbeddedId`.

    @Entity

    class User {

       @EmbeddedId

       @AttributeOverride(name="firstName", column=@Column(name="fld_firstname")

       UserId id;

       Integer age;

    }

    @Embeddable

    class UserId implements Serializable {

       String firstName;

       String lastName;

    }

You can notice that the `UserId` class is serializable. To override the column mapping, use `@AttributeOverride`.

An embedded id can itself contains the primary key of an associated entity.

    @Entity

    class Customer {

       @EmbeddedId CustomerId id;

       boolean preferredCustomer;

       @MapsId("userId")

       @JoinColumns({

          @JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),

          @JoinColumn(name="userlastname_fk", referencedColumnName="lastName")

       })

       @OneToOne User user;

    }

    @Embeddable

    class CustomerId implements Serializable {

       UserId userId;

       String customerNumber;

       //implements equals and hashCode

    }

    @Entity

    class User {

       @EmbeddedId UserId id;

       Integer age;

    }

    @Embeddable

    class UserId implements Serializable {

       String firstName;

       String lastName;

       //implements equals and hashCode

    }

In the embedded id object, the association is represented as the identifier of the associated entity. But you can link its value to a regular association in the entity via the `@MapsId` annotation. The `@MapsId` value correspond to the property name of the embedded id object containing the associated entity's identifier. In the database, it means that the `Customer.user` and the `CustomerId.userId` properties share the same underlying column (`user_fk` in this case).

## ティップ

The component type used as identifier must implement `equals()` and `hashCode()`.

In practice, your code only sets the `Customer.user` property and the user id value is copied by Hibernate into the `CustomerId.userId` property.

## 警告

The id value can be copied as late as flush time, don't rely on it until after flush time.

While not supported in JPA, Hibernate lets you place your association directly in the embedded id component (instead of having to use the `@MapsId` annotation).

    @Entity

    class Customer {

       @EmbeddedId CustomerId id;

       boolean preferredCustomer;

    }

    @Embeddable

    class CustomerId implements Serializable {

       @OneToOne

       @JoinColumns({

          @JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),

          @JoinColumn(name="userlastname_fk", referencedColumnName="lastName")

       })

       User user;

       String customerNumber;

       //implements equals and hashCode

    }

    @Entity

    class User {

       @EmbeddedId UserId id;

       Integer age;

    }

    @Embeddable

    class UserId implements Serializable {

       String firstName;

       String lastName;

       //implements equals and hashCode

    }

Let's now rewrite these examples using the hbm.xml syntax.

    <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>

First a simple example:

    <class name="User">

       <composite-id name="id" class="UserId">

          <key-property name="firstName" column="fld_firstname"/>

          <key-property name="lastName"/>

       </composite-id>

    </class>

Then an example showing how an association can be mapped.

    <class name="Customer">

       <composite-id name="id" class="CustomerId">

          <key-property name="firstName" column="userfirstname_fk"/>

          <key-property name="lastName" column="userfirstname_fk"/>

          <key-property name="customerNumber"/>

       </composite-id>

       <property name="preferredCustomer"/>

       <many-to-one name="user">

          <column name="userfirstname_fk" updatable="false" insertable="false"/>

          <column name="userlastname_fk" updatable="false" insertable="false"/>

       </many-to-one>

    </class>

    <class name="User">

       <composite-id name="id" class="UserId">

          <key-property name="firstName"/>

          <key-property name="lastName"/>

       </composite-id>

       <property name="age"/>

    </class>

Notice a few things in the previous example:

- the order of the properties (and column) matters. It must be the same between the association and the primary key of the associated entity

- the many to one uses the same columns as the primary key and thus must be marked as read only (`insertable` and `updatable` to false).

- unlike with `@MapsId`, the id value of the associated entity is not transparently copied, check the `foreign` id generator for more information.

The last example shows how to map association directly in the embedded id component.

    <class name="Customer">

       <composite-id name="id" class="CustomerId">

          <key-many-to-one name="user">

             <column name="userfirstname_fk"/>

             <column name="userlastname_fk"/>

          </key-many-to-one>

          <key-property name="customerNumber"/>

       </composite-id>

       <property name="preferredCustomer"/>

    </class>

    <class name="User">

       <composite-id name="id" class="UserId">

          <key-property name="firstName"/>

          <key-property name="lastName"/>

       </composite-id>

       <property name="age"/>

    </class>

This is the recommended approach to map composite identifier. The following options should not be considered unless some constraint are present.

##### 5.1.2.1.2. Multiple id properties without identifier type

Another, arguably more natural, approach is to place `@Id` on multiple properties of your entity. This approach is only supported by Hibernate (not JPA compliant) but does not require an extra embeddable component.

    @Entity

    class Customer implements Serializable {

       @Id @OneToOne

       @JoinColumns({

          @JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),

          @JoinColumn(name="userlastname_fk", referencedColumnName="lastName")

       })

       User user;

       @Id String customerNumber;

       boolean preferredCustomer;

       //implements equals and hashCode

    }

    @Entity

    class User {

       @EmbeddedId UserId id;

       Integer age;

    }

    @Embeddable

    class UserId implements Serializable {

       String firstName;

       String lastName;

       //implements equals and hashCode

    }

In this case `Customer` is its own identifier representation: it must implement `Serializable` and must implement `equals()` and `hashCode()`.

In hbm.xml, the same mapping is:

    <class name="Customer">

       <composite-id>

          <key-many-to-one name="user">

             <column name="userfirstname_fk"/>

             <column name="userlastname_fk"/>

          </key-many-to-one>

          <key-property name="customerNumber"/>

       </composite-id>

       <property name="preferredCustomer"/>

    </class>

    <class name="User">

       <composite-id name="id" class="UserId">

          <key-property name="firstName"/>

          <key-property name="lastName"/>

       </composite-id>

       <property name="age"/>

    </class>

##### 5.1.2.1.3. Multiple id properties with with a dedicated identifier type

`@IdClass` on an entity points to the class (component) representing the identifier of the class. The properties marked `@Id` on the entity must have their corresponding property on the `@IdClass`. The return type of search twin property must be either identical for basic properties or must correspond to the identifier class of the associated entity for an association.

## 警告

This approach is inherited from the EJB 2 days and we recommend against its use. But, after all it's your application and Hibernate supports it.

    @Entity

    @IdClass(CustomerId.class)

    class Customer implements Serializable {

       @Id @OneToOne

       @JoinColumns({

          @JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),

          @JoinColumn(name="userlastname_fk", referencedColumnName="lastName")

       })

       User user;

       @Id String customerNumber;

       boolean preferredCustomer;

    }

    class CustomerId implements Serializable {

       UserId user;

       String customerNumber;

       //implements equals and hashCode

    }

    @Entity

    class User {

       @EmbeddedId UserId id;

       Integer age;

       //implements equals and hashCode

    }

    @Embeddable

    class UserId implements Serializable {

       String firstName;

       String lastName;

       //implements equals and hashCode

    }

`Customer` and `CustomerId` do have the same properties `customerNumber` as well as `user`. `CustomerId` must be `Serializable` and implement `equals()` and `hashCode()`.

While not JPA standard, Hibernate let's you declare the vanilla associated property in the `@IdClass`.

    @Entity

    @IdClass(CustomerId.class)

    class Customer implements Serializable {

       @Id @OneToOne

       @JoinColumns({

          @JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),

          @JoinColumn(name="userlastname_fk", referencedColumnName="lastName")

       })

       User user;

       @Id String customerNumber;

       boolean preferredCustomer;

    }

    class CustomerId implements Serializable {

       @OneToOne User user;

       String customerNumber;

       //implements equals and hashCode

    }

    @Entity

    class User {

       @EmbeddedId UserId id;

       Integer age;

       //implements equals and hashCode

    }

    @Embeddable

    class UserId implements Serializable {

      String firstName;

      String lastName;

    }

This feature is of limited interest though as you are likely to have chosen the `@IdClass` approach to stay JPA compliant or you have a quite twisted mind.

Here are the equivalent on hbm.xml files:

    <class name="Customer">

       <composite-id class="CustomerId" mapped="true">

          <key-many-to-one name="user">

             <column name="userfirstname_fk"/>

             <column name="userlastname_fk"/>

          </key-many-to-one>

          <key-property name="customerNumber"/>

       </composite-id>

       <property name="preferredCustomer"/>

    </class>

    <class name="User">

       <composite-id name="id" class="UserId">

          <key-property name="firstName"/>

          <key-property name="lastName"/>

       </composite-id>

       <property name="age"/>

    </class>

#### 5.1.2.2. Identifier generator

Hibernate can generate and populate identifier values for you automatically. This is the recommended approach over "business" or "natural" id (especially composite ids).

Hibernate offers various generation strategies, let's explore the most common ones first that happens to be standardized by JPA:

- IDENTITY: supports identity columns in DB2, MySQL, MS SQL Server, Sybase and HypersonicSQL. The returned identifier is of type `long`, `short` or `int`.

- SEQUENCE (called `seqhilo` in Hibernate): uses a hi/lo algorithm to efficiently generate identifiers of type `long`, `short` or `int`, given a named database sequence.

- TABLE (called `MultipleHiLoPerTableGenerator` in Hibernate) : uses a hi/lo algorithm to efficiently generate identifiers of type `long`, `short` or `int`, given a table and column as a source of hi values. The hi/lo algorithm generates identifiers that are unique only for a particular database.

- AUTO: selects `IDENTITY`, `SEQUENCE` or `TABLE` depending upon the capabilities of the underlying database.

## 重要項目

We recommend all new projects to use the new enhanced identifier generators. They are deactivated by default for entities using annotations but can be activated using `hibernate.id.new_generator_mappings=true`. These new generators are more efficient and closer to the JPA 2 specification semantic.

However they are not backward compatible with existing Hibernate based application (if a sequence or a table is used for id generation). See XXXXXXX ??? for more information on how to activate them.

To mark an id property as generated, use the `@GeneratedValue` annotation. You can specify the strategy used (default to `AUTO`) by setting `strategy`.

    @Entity

    public class Customer {

       @Id @GeneratedValue

       Integer getId() { ... };

    }

    @Entity

    public class Invoice {

       @Id @GeneratedValue(strategy=GenerationType.IDENTITY)

       Integer getId() { ... };

    }

`SEQUENCE` and `TABLE` require additional configurations that you can set using `@SequenceGenerator` and `@TableGenerator`:

- `name`: name of the generator

- `table` / `sequenceName`: name of the table or the sequence (defaulting respectively to `hibernate_sequences` and `hibernate_sequence`)

- `catalog` / `schema`:

- `initialValue`: the value from which the id is to start generating

- `allocationSize`: the amount to increment by when allocating id numbers from the generator

In addition, the `TABLE` strategy also let you customize:

- `pkColumnName`: the column name containing the entity identifier

- `valueColumnName`: the column name containing the identifier value

- `pkColumnValue`: the entity identifier

- `uniqueConstraints`: any potential column constraint on the table containing the ids

To link a table or sequence generator definition with an actual generated property, use the same name in both the definition `name` and the generator value `generator` as shown below.

    @Id

    @GeneratedValue(

        strategy=GenerationType.SEQUENCE,

        generator="SEQ_GEN")

    @javax.persistence.SequenceGenerator(

        name="SEQ_GEN",

        sequenceName="my_sequence",

        allocationSize=20

    )

    public Integer getId() { ... }

The scope of a generator definition can be the application or the class. Class-defined generators are not visible outside the class and can override application level generators. Application level generators are defined in JPA's XML deployment descriptors (see XXXXXX ???):

    <table-generator name="EMP_GEN"

                table="GENERATOR_TABLE"

                pk-column-name="key"

                value-column-name="hi"

                pk-column-value="EMP"

                allocation-size="20"/>

    //and the annotation equivalent

    @javax.persistence.TableGenerator(

        name="EMP_GEN",

        table="GENERATOR_TABLE",

        pkColumnName = "key",

        valueColumnName = "hi"

        pkColumnValue="EMP",

        allocationSize=20

    )

    <sequence-generator name="SEQ_GEN"

        sequence-name="my_sequence"

        allocation-size="20"/>

    //and the annotation equivalent

    @javax.persistence.SequenceGenerator(

        name="SEQ_GEN",

        sequenceName="my_sequence",

        allocationSize=20

    )

If a JPA XML descriptor (like `META-INF/orm.xml`) is used to define the generators, `EMP_GEN` and `SEQ_GEN` are application level generators.

## 注意

Package level definition is not supported by the JPA specification. However, you can use the `@GenericGenerator` at the package level (see ???).

These are the four standard JPA generators. Hibernate goes beyond that and provide additional generators or additional options as we will see below. You can also write your own custom identifier generator by implementing `org.hibernate.id.IdentifierGenerator`.

To define a custom generator, use the `@GenericGenerator` annotation (and its plural counter part `@GenericGenerators`) that describes the class of the identifier generator or its short cut name (as described below) and a list of key/value parameters. When using `@GenericGenerator` and assigning it via `@GeneratedValue.generator`, the `@GeneratedValue.strategy` is ignored: leave it blank.

    @Id @GeneratedValue(generator="system-uuid")

    @GenericGenerator(name="system-uuid", strategy = "uuid")

    public String getId() {

    @Id @GeneratedValue(generator="trigger-generated")

    @GenericGenerator(

        name="trigger-generated",

        strategy = "select",

        parameters = @Parameter(name="key", value = "socialSecurityNumber")

    )

    public String getId() {

The hbm.xml approach uses the optional `<generator>` child element inside `<id>`. If any parameters are required to configure or initialize the generator instance, they are passed using the `<param>` element.

    <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>

##### 5.1.2.2.1. Various additional generators

すべてのジェネレータは、 `org.hibernate.id.IdentifierGenerator` インターフェースを実装します。これはとても単純なインターフェースなので、特別な実装を独自に用意するアプリケーションもあるかもしれません。しかし Hibernate は組み込みの実装をいくつも用意しています。組み込みのジェネレータには以下のショートカット名があります：

`increment`

  `long` , `short` , `int` 型の識別子を生成します。これらは他のプロセスが同じテーブルにデータを挿入しないときだけユニークです。 クラスタ内では使わないでください 。

`identity`

  DB2, MySQL, MS SQL Server, Sybase, HypersonicSQL の識別子カラムをサポートします。返される識別子の型は `long` , `short` , `int` のいずれかです。

`sequence`

  DB2, PostgreSQL, Oracle, SAP DB, McKoi のシーケンスや、 Interbase のジェネレータを使用します。返される識別子の型は `long` , `short` , `int` のいずれかです。

`hilo`

  `long` , `short` , `int` 型の識別子を効率的に生成する hi/lo アルゴリズムを使います。 hi 値のソースとして、テーブルとカラムを与えます(デフォルトではそれぞれ `hibernate_unique_key` と `next_hi` )。 hi/lo アルゴリズムは特定のデータベースに対してのみユニークな識別子を生成します。

`seqhilo`

  `long` , `short` , `int` 型の識別子を効率的に生成する hi/lo アルゴリズムを使います。指定されたデータベースシーケンスを与えます。

`uuid`

  Generates a 128-bit UUID based on a custom algorithm. The value generated is represented as a string of 32 hexidecimal digits. Users can also configure it to use a separator (config parameter "separator") which separates the hexidecimal digits into 8{sep}8{sep}4{sep}8{sep}4. Note specifically that this is different than the IETF RFC 4122 representation of 8-4-4-4-12. If you need RFC 4122 compliant UUIDs, consider using "uuid2" generator discussed below.

`uuid2`

  Generates a IETF RFC 4122 compliant (variant 2) 128-bit UUID. The exact "version" (the RFC term) generated depends on the pluggable "generation strategy" used (see below). Capable of generating values as `java.util.UUID`, `java.lang.String` or as a byte array of length 16 (`byte[16]`). The "generation strategy" is defined by the interface `org.hibernate.id.UUIDGenerationStrategy`. The generator defines 2 configuration parameters for defining which generation strategy to use:

  `uuid_gen_strategy_class`

    Names the UUIDGenerationStrategy class to use

  `uuid_gen_strategy`

    Names the UUIDGenerationStrategy instance to use

  Out of the box, comes with the following strategies:

  - `org.hibernate.id.uuid.StandardRandomStrategy` (the default) - generates "version 3" (aka, "random") UUID values via the `randomUUID` method of `java.util.UUID`

  - `org.hibernate.id.uuid.CustomVersionOneStrategy` - generates "version 1" UUID values, using IP address since mac address not available. If you need mac address to be used, consider leveraging one of the existing third party UUID generators which sniff out mac address and integrating it via the `org.hibernate.id.UUIDGenerationStrategy` contract. Two such libraries known at time of this writing include http://johannburkard.de/software/uuid/ and http://commons.apache.org/sandbox/id/uuid.html

`guid`

  MS SQL サーバーと MySQL でデータベースが生成する GUID 文字列を使用します。

`native`

  使用するデータベースの性能により `identity` 、 `sequence` 、 `hilo` のいずれかが選ばれます。

`assigned`

  `save()` が呼ばれる前に、アプリケーションがオブジェクトに識別子を代入できるようにします。 `<generator>` 要素が指定されていなければ、これがデフォルトの戦略になります。

`select`

  あるユニークキーによる行の選択と主キーの値の復元により、データベーストリガが割り当てた主キーを取得します。

`foreign`

  他の関連オブジェクトの識別子を使います。普通は、 `<one-to-one>` 主キー関連と組み合わせて使います。

`sequence-identity`

  実際の値の生成のためにデータベースシーケンスを使用する特別なシーケンス生成戦略ですが、 JDBC3 getGeneratedKeys と結びついて、 INSERT 文の実行の一部として生成された識別子の値を実際に返します。この戦略は JDK 1.4 を対象とする Oracle 10g のドライバでサポートされていることが知られています。これらの INSERT 文でのコメントは Oracle のドライバのバグにより無効にされていることに注意してください。

##### 5.1.2.2.2. Hi/lo アルゴリズム

`hilo` と `seqhilo` ジェネレータは、識別子生成の代表的なアプローチである hi/lo アルゴリズムの2つの代替実装を提供します。1番目の実装は、次回に利用される "hi" 値を保持する「特別な」データベーステーブルを必要とします。2番目の実装は、 Oracle スタイルのシーケンスを使います（サポートされている場合）。

    <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>

    <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>

残念ながら Hibernate への独自の `Connection` を提供するときには、 `hilo` を使えません。 Hibernate が JTA でリストされている接続を取得するためにアプリケーションサーバーのデータソースを使用しているときには、 `hibernate.transaction.manager_lookup_class` を適切に設定しなければなりません。

##### 5.1.2.2.3. UUID アルゴリズム

UUID には以下のものが含まれます： IP アドレス、 JVM のスタートアップタイム（4分の1秒の正確さ）、システム時間、（ JVM に対してユニークな）カウンタ値。 Java コードから MAC アドレスやメモリアドレスを取得することはできないので、 JNI が使えないときの最良の方法です。

##### 5.1.2.2.4. 識別子カラムとシーケンス

識別子カラムをサポートしているデータベース（DB2, MySQL, Sybase, MS SQL）では、 `identity` キー生成が使えます。シーケンスをサポートするデータベース（DB2, Oracle, PostgreSQL, Interbase, McKoi, SAP DB）では、 `sequence` スタイルのキー生成が使えます。どちらの戦略も、新しいオブジェクトを挿入するために、 SQL クエリを2つ必要とします。

    <id name="id" type="long" column="person_id">

            <generator class="sequence">

                    <param name="sequence">person_id_sequence</param>

            </generator>

    </id>

    <id name="id" type="long" column="person_id" unsaved-value="0">

            <generator class="identity"/>

    </id>

クロスプラットフォームの開発では、`native` 戦略は `identity` 、 `sequence` 、 `hilo` 戦略の中から1つを選択しますが、これは使用しているデータベースの能力に依存します。

##### 5.1.2.2.5. 識別子の割り当て

If you want the application to assign identifiers, as opposed to having Hibernate generate them, you can use the `assigned` generator. This special generator uses the identifier value already assigned to the object's identifier property. The generator is used when the primary key is a natural key instead of a surrogate key. This is the default behavior if you do not specify `@GeneratedValue` nor `<generator>` elements.

`assigned` ジェネレータを選択すると、 Hibernate は `unsaved-value="undefined"` を使います。そして、バージョンやタイムスタンプのプロパティがない場合や `Interceptor.isUnsaved()` を定義しなかった場合には、インスタンスが一時的(transient)なものであるのか、またはセッションから分離(detached)したものかどうかを決めるために、データベースを調べます。

##### 5.1.2.2.6. トリガにより割り当てられた主キー

レガシースキーマのためにのみ指定します( Hibernate はトリガを使って DDL を生成しません)。

    <id name="id" type="long" column="person_id">

            <generator class="select">

                    <param name="key">socialSecurityNumber</param>

            </generator>

    </id>

上記の例の中で、クラスで自然キーとして定義された `socialSecurityNumber` という名前のユニークな値のプロパティと、値がトリガにより生成される `person_id` という名前の代理キーがあります。

##### 5.1.2.2.7. Identity copy (foreign generator)

Finally, you can ask Hibernate to copy the identifier from another associated entity. In the Hibernate jargon, it is known as a foreign generator but the JPA mapping reads better and is encouraged.

    @Entity

    class MedicalHistory implements Serializable {

      @Id @OneToOne

      @JoinColumn(name = "person_id")

      Person patient;

    }

    @Entity

    public class Person implements Serializable {

      @Id @GeneratedValue Integer id;

    }

Or alternatively

    @Entity

    class MedicalHistory implements Serializable {

      @Id Integer id;

      @MapsId @OneToOne

      @JoinColumn(name = "patient_id")

      Person patient;

    }

    @Entity

    class Person {

      @Id @GeneratedValue Integer id;

    }

In hbm.xml use the following approach:

    <class name="MedicalHistory">

       <id name="id">

          <generator class="foreign">

             <param name="property">patient</param>

          </generator>

       </id>

       <one-to-one name="patient" class="Person" constrained="true"/>

    </class>

#### 5.1.2.3. Enhanced identifier generators

Starting with release 3.2.3, there are 2 new generators which represent a re-thinking of 2 different aspects of identifier generation. The first aspect is database portability; the second is optimization Optimization means that you do not have to query the database for every request for a new identifier value. These two new generators are intended to take the place of some of the named generators described above, starting in 3.3.x. However, they are included in the current releases and can be referenced by FQN.

The first of these new generators is `org.hibernate.id.enhanced.SequenceStyleGenerator` which is intended, firstly, as a replacement for the `sequence` generator and, secondly, as a better portability generator than `native`. This is because `native` generally chooses between `identity` and `sequence` which have largely different semantics that can cause subtle issues in applications eyeing portability. `org.hibernate.id.enhanced.SequenceStyleGenerator`, however, achieves portability in a different manner. It chooses between a table or a sequence in the database to store its incrementing values, depending on the capabilities of the dialect being used. The difference between this and `native` is that table-based and sequence-based storage have the same exact semantic. In fact, sequences are exactly what Hibernate tries to emulate with its table-based generators. This generator has a number of configuration parameters:

- `sequence_name` (optional, defaults to `hibernate_sequence`): the name of the sequence or table to be used.

- `initial_value` (optional, defaults to `1`): the initial value to be retrieved from the sequence/table. In sequence creation terms, this is analogous to the clause typically named "STARTS WITH".

- `increment_size` (optional - defaults to `1`): the value by which subsequent calls to the sequence/table should differ. In sequence creation terms, this is analogous to the clause typically named "INCREMENT BY".

- `force_table_use` (optional - defaults to `false`): should we force the use of a table as the backing structure even though the dialect might support sequence?

- `value_column` (optional - defaults to `next_val`): only relevant for table structures, it is the name of the column on the table which is used to hold the value.

- `optimizer` (optional - defaults to `none`): See 「Identifier generator optimization」

The second of these new generators is `org.hibernate.id.enhanced.TableGenerator`, which is intended, firstly, as a replacement for the `table` generator, even though it actually functions much more like `org.hibernate.id.MultipleHiLoPerTableGenerator`, and secondly, as a re-implementation of `org.hibernate.id.MultipleHiLoPerTableGenerator` that utilizes the notion of pluggable optimizers. Essentially this generator defines a table capable of holding a number of different increment values simultaneously by using multiple distinctly keyed rows. This generator has a number of configuration parameters:

- `table_name` (optional - defaults to `hibernate_sequences`): the name of the table to be used.

- `value_column_name` (optional - defaults to `next_val`): the name of the column on the table that is used to hold the value.

- `segment_column_name` (optional - defaults to `sequence_name`): the name of the column on the table that is used to hold the "segment key". This is the value which identifies which increment value to use.

- `segment_value` (optional - defaults to `default`): The "segment key" value for the segment from which we want to pull increment values for this generator.

- `segment_value_length` (optional - defaults to `255`): Used for schema generation; the column size to create this segment key column.

- `initial_value` (optional - defaults to `1`): The initial value to be retrieved from the table.

- `increment_size` (optional - defaults to `1`): The value by which subsequent calls to the table should differ.

- `optimizer` (optional - defaults to `??`): See 「Identifier generator optimization」.

##### 5.1.2.3.1. Identifier generator optimization

For identifier generators that store values in the database, it is inefficient for them to hit the database on each and every call to generate a new identifier value. Instead, you can group a bunch of them in memory and only hit the database when you have exhausted your in-memory value group. This is the role of the pluggable optimizers. Currently only the two enhanced generators (「Enhanced identifier generators」 support this operation.

- `none` (generally this is the default if no optimizer was specified): this will not perform any optimizations and hit the database for each and every request.

- `hilo`: applies a hi/lo algorithm around the database retrieved values. The values from the database for this optimizer are expected to be sequential. The values retrieved from the database structure for this optimizer indicates the "group number". The `increment_size` is multiplied by that value in memory to define a group "hi value".

- `pooled`: as with the case of `hilo`, this optimizer attempts to minimize the number of hits to the database. Here, however, we simply store the starting value for the "next group" into the database structure rather than a sequential value in combination with an in-memory grouping algorithm. Here, `increment_size` refers to the values coming from the database.

#### 5.1.2.4. Partial identifier generation

Hibernate supports the automatic generation of some of the identifier properties. Simply use the `@GeneratedValue` annotation on one or several id properties.

## 警告

The Hibernate team has always felt such a construct as fundamentally wrong. Try hard to fix your data model before using this feature.

    @Entity

    public class CustomerInventory implements Serializable {

      @Id

      @TableGenerator(name = "inventory",

        table = "U_SEQUENCES",

        pkColumnName = "S_ID",

        valueColumnName = "S_NEXTNUM",

        pkColumnValue = "inventory",

        allocationSize = 1000)

      @GeneratedValue(strategy = GenerationType.TABLE, generator = "inventory")

      Integer id;

      @Id @ManyToOne(cascade = CascadeType.MERGE)

      Customer customer;

    }

    @Entity

    public class Customer implements Serializable {

       @Id

       private int id;

    }

You can also generate properties inside an `@EmbeddedId` class.

### 5.1.3. Optimistic locking properties (optional)

When using long transactions or conversations that span several database transactions, it is useful to store versioning data to ensure that if the same entity is updated by two conversations, the last to commit changes will be informed and not override the other conversation's work. It guarantees some isolation while still allowing for good scalability and works particularly well in read-often write-sometimes situations.

You can use two approaches: a dedicated version number or a timestamp.

A version or timestamp property should never be null for a detached instance. Hibernate will detect any instance with a null version or timestamp as transient, irrespective of what other `unsaved-value` strategies are specified. Declaring a nullable version or timestamp property is an easy way to avoid problems with transitive reattachment in Hibernate. It is especially useful for people using assigned identifiers or composite keys.

#### 5.1.3.1. Version number

You can add optimistic locking capability to an entity using the `@Version` annotation:

    @Entity

    public class Flight implements Serializable {

    ...

        @Version

        @Column(name="OPTLOCK")

        public Integer getVersion() { ... }

    }

The version property will be mapped to the `OPTLOCK` column, and the entity manager will use it to detect conflicting updates (preventing lost updates you might otherwise see with the last-commit-wins strategy).

The version column may be a numeric. Hibernate supports any kind of type provided that you define and implement the appropriate `UserVersionType`.

The application must not alter the version number set up by Hibernate in any way. To artificially increase the version number, check in Hibernate Entity Manager's reference documentation `LockModeType.OPTIMISTIC_FORCE_INCREMENT` or `LockModeType.PESSIMISTIC_FORCE_INCREMENT`.

If the version number is generated by the database (via a trigger for example), make sure to use `@org.hibernate.annotations.Generated(GenerationTime.ALWAYS).`

To declare a version property in hbm.xml, use:

    <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|."
    />

| `column` （オプション - デフォルトはプロパティ名）: バージョン番号を保持するカラムの名前。
| `name` ：永続クラスのプロパティの名前。
| `type` （オプション - デフォルトは `integer` ）：バージョン番号の型。
| `access` (オプション - デフォルトは `property` ): Hibernate がプロパティの値にアクセスするために使用すべき戦略。
| `unsaved-value` (optional - defaults to `undefined`): a version property value that indicates that an instance is newly instantiated (unsaved), distinguishing it from detached instances that were saved or loaded in a previous session. `Undefined` specifies that the identifier property value should be used.
| `generated` (optional - defaults to `never`): specifies that this version property value is generated by the database. See the discussion of generated properties for more information.
| `insert` (オプション - デフォルトは `true` ): SQLの insert 文にバージョンカラムを含めるべきかどうかを指定します。もしデータベースカラムのデフォルト値が `0` と定義されるときには、 `false` に設定すると良いでしょう。

#### 5.1.3.2. Timestamp

Alternatively, you can use a timestamp. Timestamps are a less safe implementation of optimistic locking. However, sometimes an application might use the timestamps in other ways as well.

Simply mark a property of type `Date` or `Calendar` as `@Version`.

    @Entity

    public class Flight implements Serializable {

    ...

        @Version

        public Date getLastUpdate() { ... }

    }

When using timestamp versioning you can tell Hibernate where to retrieve the timestamp value from - database or JVM - by optionally adding the `@org.hibernate.annotations.Source` annotation to the property. Possible values for the value attribute of the annotation are `org.hibernate.annotations.SourceType.VM` and `org.hibernate.annotations.SourceType.DB`. The default is `SourceType.DB` which is also used in case there is no `@Source` annotation at all.

Like in the case of version numbers, the timestamp can also be generated by the database instead of Hibernate. To do that, use `@org.hibernate.annotations.Generated(GenerationTime.ALWAYS).`

In hbm.xml, use the `<timestamp>` element:

    <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|."
    />

| `column`（オプション - デフォルトはプロパティ名）： タイムスタンプを保持するカラムの名前。
| `name` ： 永続クラスである Java の `Date`型または `Timestamp` 型 の、 JavaBeans スタイルプロパティの名前。
| `access` (オプション - デフォルトは `property` ): Hibernate がプロパティの値にアクセスするために使用すべき戦略。
| `unsaved-value` （オプション - デフォルトは `null` ）： インスタンスが新しくインスタンス化された （セーブされていない）ことを示すバージョンプロパティの値。以前の Session でセーブまたはロードされた分離されたインスタンスと区別するために使われます。 （ `undefined` と指定すると、識別子プロパティの値が使われます。）
| `source` (オプション - デフォルトは `vm` ): Hibernate はどこからタイムスタンプの値を取得するべきでしょうか？データベースからでしょうか、現在の JVM からでしょうか？データベースによるタイムスタンプは、 Hibernate が "次の値" を決定するためにデータベースをヒットしなければならないため、オーバヘッドを招きます。しかしクラスタ環境では JVM から取得するより安全です。データベースの現在のタイムスタンプの取得をサポートするすべての `Dialect` が知られているわけではないことに注意してください。また一方で、精密さを欠くために、ロックで使用するには安全でないものもあります (例えば Oracle 8 )。
| `generated` (optional - defaults to `never`): specifies that this timestamp property value is actually generated by the database. See the discussion of generated properties for more information.

## 注記

`<timestamp>` は `<version type="timestamp">` と等価であることに注意してください。 `<timestamp source="db">` は `<version type="dbtimestamp">` と等価であることに注意してください。

### 5.1.4. property

You need to decide which property needs to be made persistent in a given entity. This differs slightly between the annotation driven metadata and the hbm.xml files.

#### 5.1.4.1. Property mapping with annotations

In the annotations world, every non static non transient property (field or method depending on the access type) of an entity is considered persistent, unless you annotate it as `@Transient`. Not having an annotation for your property is equivalent to the appropriate `@Basic` annotation.

The `@Basic` annotation allows you to declare the fetching strategy for a property. If set to `LAZY`, specifies that this property should be fetched lazily when the instance variable is first accessed. It requires build-time bytecode instrumentation, if your classes are not instrumented, property level lazy loading is silently ignored. The default is `EAGER`. You can also mark a property as not optional thanks to the `@Basic.optional` attribute. This will ensure that the underlying column are not nullable (if possible). Note that a better approach is to use the `@NotNull` annotation of the Bean Validation specification.

Let's look at a few examples:

    public transient int counter; //transient property

    private String firstname; //persistent property

    @Transient

    String getLengthInMeter() { ... } //transient property

    String getName() {... } // persistent property

    @Basic

    int getLength() { ... } // persistent property

    @Basic(fetch = FetchType.LAZY)

    String getDetailedComment() { ... } // persistent property

    @Temporal(TemporalType.TIME)

    java.util.Date getDepartureTime() { ... } // persistent property

    @Enumerated(EnumType.STRING)

    Starred getNote() { ... } //enum persisted as String in database

`counter`, a transient field, and `lengthInMeter`, a method annotated as `@Transient`, and will be ignored by the Hibernate. `name`, `length`, and `firstname` properties are mapped persistent and eagerly fetched (the default for simple properties). The `detailedComment` property value will be lazily fetched from the database once a lazy property of the entity is accessed for the first time. Usually you don't need to lazy simple properties (not to be confused with lazy association fetching). The recommended alternative is to use the projection capability of JP-QL (Java Persistence Query Language) or Criteria queries.

JPA support property mapping of all basic types supported by Hibernate (all basic Java types , their respective wrappers and serializable classes). Hibernate Annotations supports out of the box enum type mapping either into a ordinal column (saving the enum ordinal) or a string based column (saving the enum string representation): the persistence representation, defaulted to ordinal, can be overridden through the `@Enumerated` annotation as shown in the `note` property example.

In plain Java APIs, the temporal precision of time is not defined. When dealing with temporal data you might want to describe the expected precision in database. Temporal data can have `DATE`, `TIME`, or `TIMESTAMP` precision (ie the actual date, only the time, or both). Use the `@Temporal` annotation to fine tune that.

`@Lob` indicates that the property should be persisted in a Blob or a Clob depending on the property type: `java.sql.Clob`, `Character[]`, `char[]` and java.lang.`String` will be persisted in a Clob. `java.sql.Blob`, `Byte[]`, `byte[]` and `Serializable` type will be persisted in a Blob.

    @Lob

    public String getFullText() {

        return fullText;

    }

    @Lob

    public byte[] getFullCode() {

        return fullCode;

    }

If the property type implements `java.io.Serializable` and is not a basic type, and if the property is not annotated with `@Lob`, then the Hibernate `serializable` type is used.

##### 5.1.4.1.1. Type

You can also manually specify a type using the `@org.hibernate.annotations.Type` and some parameters if needed. `@Type.type` could be:

1. Hibernate の基本型の名前（例 `integer, string, character, date, timestamp, float, binary, serializable, object, blob` ）。

2. デフォルトの基本型の Java クラス名 （例 `int, float, char, java.lang.String, java.util.Date, java.lang.Integer, java.sql.Clob` ）。

3. シリアライズ可能な Java クラスの名前。

4. カスタム型のクラス名（例 `com.illflow.type.MyCustomType` ）。

If you do not specify a type, Hibernate will use reflection upon the named property and guess the correct Hibernate type. Hibernate will attempt to interpret the name of the return class of the property getter using, in order, rules 2, 3, and 4.

`@org.hibernate.annotations.TypeDef` and `@org.hibernate.annotations.TypeDefs` allows you to declare type definitions. These annotations can be placed at the class or package level. Note that these definitions are global for the session factory (even when defined at the class level). If the type is used on a single entity, you can place the definition on the entity itself. Otherwise, it is recommended to place the definition at the package level. In the example below, when Hibernate encounters a property of class `PhoneNumer`, it delegates the persistence strategy to the custom mapping type `PhoneNumberType`. However, properties belonging to other classes, too, can delegate their persistence strategy to `PhoneNumberType`, by explicitly using the `@Type` annotation.

## 注意

Package level annotations are placed in a file named `package-info.java` in the appropriate package. Place your annotations before the package declaration.

    @TypeDef(

       name = "phoneNumber",

       defaultForType = PhoneNumber.class,

       typeClass = PhoneNumberType.class

    )

    @Entity

    public class ContactDetails {

       [...]

       private PhoneNumber localPhoneNumber;

       @Type(type="phoneNumber")

       private OverseasPhoneNumber overseasPhoneNumber;

       [...]

    }

The following example shows the usage of the `parameters` attribute to customize the TypeDef.

    //in org/hibernate/test/annotations/entity/package-info.java

    @TypeDefs(

        {

        @TypeDef(

            name="caster",

            typeClass = CasterStringType.class,

            parameters = {

                @Parameter(name="cast", value="lower")

            }

        )

        }

    )

    package org.hibernate.test.annotations.entity;

    //in org/hibernate/test/annotations/entity/Forest.java

    public class Forest {

        @Type(type="caster")

        public String getSmallText() {

        ...

    }

When using composite user type, you will have to express column definitions. The `@Columns` has been introduced for that purpose.

    @Type(type="org.hibernate.test.annotations.entity.MonetaryAmountUserType")

    @Columns(columns = {

        @Column(name="r_amount"),

        @Column(name="r_currency")

    })

    public MonetaryAmount getAmount() {

        return amount;

    }

    public class MonetaryAmount implements Serializable {

        private BigDecimal amount;

        private Currency currency;

        ...

    }

##### 5.1.4.1.2. Access type

By default the access type of a class hierarchy is defined by the position of the `@Id` or `@EmbeddedId` annotations. If these annotations are on a field, then only fields are considered for persistence and the state is accessed via the field. If there annotations are on a getter, then only the getters are considered for persistence and the state is accessed via the getter/setter. That works well in practice and is the recommended approach.

## 注意

The placement of annotations within a class hierarchy has to be consistent (either field or on property) to be able to determine the default access type. It is recommended to stick to one single annotation placement strategy throughout your whole application.

However in some situations, you need to:

- force the access type of the entity hierarchy

- override the access type of a specific entity in the class hierarchy

- override the access type of an embeddable type

The best use case is an embeddable class used by several entities that might not use the same access type. In this case it is better to force the access type at the embeddable class level.

To force the access type on a given class, use the `@Access` annotation as showed below:

    @Entity

    public class Order {

       @Id private Long id;

       public Long getId() { return id; }

       public void setId(Long id) { this.id = id; }

       @Embedded private Address address;

       public Address getAddress() { return address; }

       public void setAddress() { this.address = address; }

    }

    @Entity

    public class User {

       private Long id;

       @Id public Long getId() { return id; }

       public void setId(Long id) { this.id = id; }

       private Address address;

       @Embedded public Address getAddress() { return address; }

       public void setAddress() { this.address = address; }

    }

    @Embeddable

    @Access(AcessType.PROPERTY)

    public class Address {

       private String street1;

       public String getStreet1() { return street1; }

       public void setStreet1() { this.street1 = street1; }

       private hashCode; //not persistent

    }

You can also override the access type of a single property while keeping the other properties standard.

    @Entity

    public class Order {

       @Id private Long id;

       public Long getId() { return id; }

       public void setId(Long id) { this.id = id; }

       @Transient private String userId;

       @Transient private String orderId;

       @Access(AccessType.PROPERTY)

       public String getOrderNumber() { return userId + ":" + orderId; }

       public void setOrderNumber() { this.userId = ...; this.orderId = ...; }

    }

In this example, the default access type is `FIELD` except for the `orderNumber` property. Note that the corresponding field, if any must be marked as `@Transient` or `transient`.

## @org.hibernate.annotations.AccessType

The annotation `@org.hibernate.annotations.AccessType` should be considered deprecated for FIELD and PROPERTY access. It is still useful however if you need to use a custom access type.

##### 5.1.4.1.3. Optimistic lock

It is sometimes useful to avoid increasing the version number even if a given property is dirty (particularly collections). You can do that by annotating the property (or collection) with `@OptimisticLock(excluded=true)`.

More formally, specifies that updates to this property do not require acquisition of the optimistic lock.

##### 5.1.4.1.4. Declaring column attributes

The column(s) used for a property mapping can be defined using the `@Column` annotation. Use it to override default values (see the JPA specification for more information on the defaults). You can use this annotation at the property level for properties that are:

- not annotated at all

- annotated with `@Basic`

- annotated with `@Version`

- annotated with `@Lob`

- annotated with `@Temporal`

    @Entity

    public class Flight implements Serializable {

    ...

    @Column(updatable = false, name = "flight_name", nullable = false, length=50)

    public String getName() { ... }

The `name` property is mapped to the `flight_name` column, which is not nullable, has a length of 50 and is not updatable (making the property immutable).

This annotation can be applied to regular properties as well as `@Id` or `@Version` properties.

    @Column(
        name="columnName";
        boolean unique() default false;
        boolean nullable() default true;
        boolean insertable() default true;
        boolean updatable() default true;
        String columnDefinition() default "";
        String table() default "";
        int length() default 255;
        int precision() default 0; // decimal precision
        int scale() default 0; // decimal scale

| `name` (optional): the column name (default to the property name)
| `unique` (optional): set a unique constraint on this column or not (default false)
| `nullable` (optional): set the column as nullable (default true).
| `insertable` (optional): whether or not the column will be part of the insert statement (default true)
| `updatable` (optional): whether or not the column will be part of the update statement (default true)
| `columnDefinition` (optional): override the sql DDL fragment for this particular column (non portable)
| `table` (optional): define the targeted table (default primary table)
| ``length`` (optional): column length (default 255)
| ``precision`` (optional): column decimal precision (default 0)
| ``scale`` (optional): column decimal scale if useful (default 0)

##### 5.1.4.1.5. Formula

Sometimes, you want the Database to do some computation for you rather than in the JVM, you might also create some kind of virtual column. You can use a SQL fragment (aka formula) instead of mapping a property into a column. This kind of property is read only (its value is calculated by your formula fragment).

    @Formula("obj_length * obj_height * obj_width")

    public long getObjectVolume()

The SQL fragment can be as complex as you want and even include subselects.

##### 5.1.4.1.6. Non-annotated property defaults

If a property is not annotated, the following rules apply:

- If the property is of a single type, it is mapped as @Basic

- Otherwise, if the type of the property is annotated as @Embeddable, it is mapped as @Embedded

- Otherwise, if the type of the property is `Serializable`, it is mapped as `@Basic` in a column holding the object in its serialized version

- Otherwise, if the type of the property is `java.sql.Clob` or `java.sql.Blob`, it is mapped as `@Lob` with the appropriate `LobType`

#### 5.1.4.2. Property mapping with hbm.xml

`<property>` 要素は、クラスの永続的な JavaBean スタイルのプロパティを定義します。

    <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"
    />

| `name`： 小文字で始まるプロパティ名。
| `column`（オプション - デフォルトはプロパティ名）： マッピングされたデータベーステーブルのカラムの名前。ネストした `<column>` 要素でも指定できます。
| `type`（オプション）： Hibernate の型を示す名前。
| `update, insert` （オプション - デフォルトは `true` ）： マッピングされたカラムが SQL の `UPDATE` や `INSERT` に含まれることを指定します。両方とも `false` に設定すると、同じカラムにマッピングされた他のプロパティやトリガや他のアプリケーションによって初期化された純粋な「導出」プロパティが可能になります。
| `formula`（オプション）： 計算 プロパティのための値を定義する SQL 式。計算されたプロパティは自身のカラムへのマッピングがありません。
| `access` (オプション - デフォルトは `property` ): Hibernate がプロパティの値にアクセスするために使用すべき戦略。
| `lazy` (オプション - デフォルトは `false` ): インスタンス変数に最初にアクセスしたときに、プロパティを遅延して取得するよう指定します。 (バイトコード実装を作成する時間が必要になります)。
| `unique` (オプション):カラムにユニーク制約をつける DDL の生成を可能にします。また、 `property-ref` のターゲットとすることもできます。
| `not-null` (optional): enables the DDL generation of a nullability constraint for the columns.
| `optimistic-lock` (オプション - デフォルトは `true` ): このプロパティの更新に楽観ロックの取得を要求するかどうかを指定します。言い換えれば、このプロパティがダーティであるときにバージョンを増やすべきかを決定します。
| `generated` (optional - defaults to `never`): specifies that this property value is actually generated by the database. See the discussion of generated properties for more information.

typename には以下の値が可能です：

1. Hibernate の基本型の名前（例 `integer, string, character, date, timestamp, float, binary, serializable, object, blob` ）。

2. デフォルトの基本型の Java クラス名 （例 `int, float, char, java.lang.String, java.util.Date, java.lang.Integer, java.sql.Clob` ）。

3. シリアライズ可能な Java クラスの名前。

4. カスタム型のクラス名（例 `com.illflow.type.MyCustomType` ）。

型を指定しなければ、 Hibernate は正しい Hibernate の型を推測するために、指定されたプロパティに対してリフレクションを使います。 Hibernate はルール2, 3, 4をその順序に使い、 getter プロパティの返り値のクラスの名前を解釈しようとします。しかしこれで常に十分であるとは限りません。場合によっては、 `type` 属性が必要な場合があります。 （例えば `Hibernate.DATE` と `Hibernate.TIMESTAMP` を区別するため、またはカスタム型を指定するためなどです。）

`access` 属性で、実行時に Hibernate がどのようにプロパティにアクセスするかを制御できます。デフォルトでは Hibernate はプロパティの get/set のペアをコールします。 `access="field"` と指定すれば、 Hibernate はリフレクションを使い get/set のペアを介さずに、直接フィールドにアクセスします。インターフェース `org.hibernate.property.PropertyAccessor` を実装するクラスを指定することで、プロパティへのアクセスに独自の戦略を指定することができます。

特に強力な特徴は生成プロパティです。これらのプロパティは当然読み取り専用であり、プロパティの値はロード時に計算されます。計算を SQL 式として宣言すると、このプロパティはインスタンスをロードする SQL クエリの `SELECT` 句のサブクエリに変換されます:

    <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 )"/>

特定のカラム(例では `customerId` がそれにあたります)のエイリアスを宣言することなく、エンティティ自身のテーブルを参照できることに注意してください。もし属性を使用したくなければ、ネストした `<formula>` マッピング要素を使えることにも注意してください。

### 5.1.5. Embedded objects (aka components)

Embeddable objects (or components) are objects whose properties are mapped to the same table as the owning entity's table. Components can, in turn, declare their own properties, components or collections

It is possible to declare an embedded component inside an entity and even override its column mapping. Component classes have to be annotated at the class level with the `@Embeddable` annotation. It is possible to override the column mapping of an embedded object for a particular entity using the `@Embedded` and `@AttributeOverride` annotation in the associated property:

    @Entity

    public class Person implements Serializable {

        // Persistent component using defaults

        Address homeAddress;

        @Embedded

        @AttributeOverrides( {

                @AttributeOverride(name="iso2", column = @Column(name="bornIso2") ),

                @AttributeOverride(name="name", column = @Column(name="bornCountryName") )

        } )

        Country bornIn;

        ...

    }

    @Embeddable

    public class Address implements Serializable {

        String city;

        Country nationality; //no overriding here

    }

    @Embeddable

    public class Country implements Serializable {

        private String iso2;

        @Column(name="countryName") private String name;

        public String getIso2() { return iso2; }

        public void setIso2(String iso2) { this.iso2 = iso2; }

        public String getName() { return name; }

        public void setName(String name) { this.name = name; }

        ...

    }

An embeddable object inherits the access type of its owning entity (note that you can override that using the `@Access` annotation).

The `Person` entity has two component properties, `homeAddress` and `bornIn`. `homeAddress` property has not been annotated, but Hibernate will guess that it is a persistent component by looking for the `@Embeddable` annotation in the Address class. We also override the mapping of a column name (to `bornCountryName`) with the `@Embedded` and `@AttributeOverride` annotations for each mapped attribute of `Country`. As you can see, `Country` is also a nested component of `Address`, again using auto-detection by Hibernate and JPA defaults. Overriding columns of embedded objects of embedded objects is through dotted expressions.

    @Embedded

        @AttributeOverrides( {

                @AttributeOverride(name="city", column = @Column(name="fld_city") ),

                @AttributeOverride(name="nationality.iso2", column = @Column(name="nat_Iso2") ),

                @AttributeOverride(name="nationality.name", column = @Column(name="nat_CountryName") )

                //nationality columns in homeAddress are overridden

        } )

        Address homeAddress;

Hibernate Annotations supports something that is not explicitly supported by the JPA specification. You can annotate a embedded object with the `@MappedSuperclass` annotation to make the superclass properties persistent (see `@MappedSuperclass` for more informations).

You can also use association annotations in an embeddable object (ie `@OneToOne`, `@ManyToOne`, `@OneToMany` or `@ManyToMany`). To override the association columns you can use `@AssociationOverride`.

If you want to have the same embeddable object type twice in the same entity, the column name defaulting will not work as several embedded objects would share the same set of columns. In plain JPA, you need to override at least one set of columns. Hibernate, however, allows you to enhance the default naming mechanism through the `NamingStrategy` interface. You can write a strategy that prevent name clashing in such a situation. `DefaultComponentSafeNamingStrategy` is an example of this.

If a property of the embedded object points back to the owning entity, annotate it with the `@Parent` annotation. Hibernate will make sure this property is properly loaded with the entity reference.

In XML, use the `<component>` element.

    <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>

| `name`：プロパティ名。
| `class` （オプション - デフォルトはリフレクションにより決定されるプロパティの型）： コンポーネント（子）クラスの名前。
| `insert`：マッピングされたカラムが SQL の `INSERT` に現れるようにするかどうかを指定します。
| `update`：マッピングされたカラムが SQL の `UPDATE` に現れるようにするかどうかを指定します。
| `access` (オプション - デフォルトは `property` ): Hibernate がプロパティの値にアクセスするために使用すべき戦略。
| `lazy` (オプション - デフォルトは `false` ): インスタンス変数に最初にアクセスしたときに、コンポーネントを遅延してフェッチするよう指定します。 (バイトコード実装を作成する時間が必要になります)
| `optimistic-lock` (オプション - デフォルトは `true` ): このプロパティの更新に、楽観ロックの取得を要求するかどうかを指定します。言い換えれば、このプロパティがダーティであるときにバージョンを増やすべきかを決定します。
| `unique` (オプション - デフォルトは `false` ): コンポーネントのすべてのマッピングするカラムに、ユニーク制約が存在するかを指定します。

子の `<property>` タグで、子のクラスのプロパティをテーブルカラムにマッピングします。

`<component>` 要素は、親エンティティへ戻る参照として、コンポーネントのクラスのプロパティをマッピングする `<parent>` サブ要素を許可します。

The `<dynamic-component>` element allows a `Map` to be mapped as a component, where the property names refer to keys of the map. See 「動的コンポーネント」 for more information. This feature is not supported in annotations.

### 5.1.6. Inheritance strategy

Java is a language supporting polymorphism: a class can inherit from another. Several strategies are possible to persist a class hierarchy:

- Single table per class hierarchy strategy: a single table hosts all the instances of a class hierarchy

- Joined subclass strategy: one table per class and subclass is present and each table persist the properties specific to a given subclass. The state of the entity is then stored in its corresponding class table and all its superclasses

- Table per class strategy: one table per concrete class and subclass is present and each table persist the properties of the class and its superclasses. The state of the entity is then stored entirely in the dedicated table for its class.

#### 5.1.6.1. Single table per class hierarchy strategy

With this approach the properties of all the subclasses in a given mapped class hierarchy are stored in a single table.

Each subclass declares its own persistent properties and subclasses. Version and id properties are assumed to be inherited from the root class. Each subclass in a hierarchy must define a unique discriminator value. If this is not specified, the fully qualified Java class name is used.

    @Entity

    @Inheritance(strategy=InheritanceType.SINGLE_TABLE)

    @DiscriminatorColumn(

        name="planetype",

        discriminatorType=DiscriminatorType.STRING

    )

    @DiscriminatorValue("Plane")

    public class Plane { ... }

    @Entity

    @DiscriminatorValue("A320")

    public class A320 extends Plane { ... }

In hbm.xml, for the table-per-class-hierarchy mapping strategy, the `<subclass>` declaration is used. For example:

    <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>

| `name`：サブクラスの完全修飾されたクラス名。
| `discriminator-value`（オプション - デフォルトはクラス名）： 個々のサブクラスを区別するための値。
| `proxy` (オプション): 遅延初期化プロキシに使用するクラスやインターフェースを指定します。
| `lazy` (オプション、デフォルトは `true` ): `lazy="false"` とすると、遅延フェッチが使用できません。

For information about inheritance mappings see 10章継承マッピング.

##### 5.1.6.1.1. discriminator

Discriminators are required for polymorphic persistence using the table-per-class-hierarchy mapping strategy. It declares a discriminator column of the table. The discriminator column contains marker values that tell the persistence layer what subclass to instantiate for a particular row. Hibernate Core supports the follwoing restricted set of types as discriminator column: `string`, `character`, `integer`, `byte`, `short`, `boolean`, `yes_no`, `true_false`.

Use the `@DiscriminatorColumn` to define the discriminator column as well as the discriminator type.

## 注意

`The enum DiscriminatorType` used in `javax.persitence.DiscriminatorColumn` only contains the values `STRING`, `CHAR` and `INTEGER` which means that not all Hibernate supported types are available via the `@DiscriminatorColumn` annotation.

You can also use `@DiscriminatorFormula` to express in SQL a virtual discriminator column. This is particularly useful when the discriminator value can be extracted from one or more columns of the table. Both `@DiscriminatorColumn` and `@DiscriminatorFormula` are to be set on the root entity (once per persisted hierarchy).

`@org.hibernate.annotations.DiscriminatorOptions` allows to optionally specify Hibernate specific discriminator options which are not standardized in JPA. The available options are `force` and `insert`. The `force` attribute is useful if the table contains rows with "extra" discriminator values that are not mapped to a persistent class. This could for example occur when working with a legacy database. If `force` is set to `true` Hibernate will specify the allowed discriminator values in the `SELECT` query, even when retrieving all instances of the root class. The second option - `insert` - tells Hibernate whether or not to include the discriminator column in SQL `INSERTs`. Usually the column should be part of the `INSERT` statement, but if your discriminator column is also part of a mapped composite identifier you have to set this option to `false`.

## ティップ

There is also a `@org.hibernate.annotations.ForceDiscriminator` annotation which is deprecated since version 3.6. Use `@DiscriminatorOptions` instead.

Finally, use `@DiscriminatorValue` on each class of the hierarchy to specify the value stored in the discriminator column for a given entity. If you do not set `@DiscriminatorValue` on a class, the fully qualified class name is used.

    @Entity

    @Inheritance(strategy=InheritanceType.SINGLE_TABLE)

    @DiscriminatorColumn(

        name="planetype",

        discriminatorType=DiscriminatorType.STRING

    )

    @DiscriminatorValue("Plane")

    public class Plane { ... }

    @Entity

    @DiscriminatorValue("A320")

    public class A320 extends Plane { ... }

In hbm.xml, the `<discriminator>` element is used to define the discriminator column or formula:

    <discriminator
            column="discriminator_column"
            type="discriminator_type"
            force="true|false"
            insert="true|false"
            formula="arbitrary sql expression"
    />

| `column`（オプション - デフォルトは `class` ）： 識別カラムの名前。
| `type` （オプション - デフォルトは `string` ）： Hibernate の型を示す名前。
| `force` （オプション - デフォルトは `false` ）： ルートクラスのすべてのインスタンスを検索する場合であっても、 Hibernate が使用できる識別カラムの指定を「強制」します。
| `insert` （オプション - デフォルトは `true` ）： もし識別カラムがマッピングする複合識別子の一部ならば、 `false` と設定してください。 (Hibernate に SQL の `INSERT` 内のカラムを含ませないよう伝えます。)
| `formula` (オプション) 型が評価されるときに実行される任意の SQL 式。コンテンツベースの識別を可能にします。

識別カラムの実際の値は、 `<class>` と `<subclass>` 要素の `discriminator-value` 属性で指定されます。

`formula` 属性を使うと、行の型を評価するために任意の SQL 式を宣言できます:

    <discriminator

        formula="case when CLASS_TYPE in ('a', 'b', 'c') then 0 else 1 end"

        type="integer"/>

#### 5.1.6.2. Joined subclass strategy

Each subclass can also be mapped to its own table. This is called the table-per-subclass mapping strategy. An inherited state is retrieved by joining with the table of the superclass. A discriminator column is not required for this mapping strategy. Each subclass must, however, declare a table column holding the object identifier. The primary key of this table is also a foreign key to the superclass table and described by the `@PrimaryKeyJoinColumn`s or the `<key>` element.

    @Entity @Table(name="CATS")

    @Inheritance(strategy=InheritanceType.JOINED)

    public class Cat implements Serializable {

        @Id @GeneratedValue(generator="cat-uuid")

        @GenericGenerator(name="cat-uuid", strategy="uuid")

        String getId() { return id; }

        ...

    }

    @Entity @Table(name="DOMESTIC_CATS")

    @PrimaryKeyJoinColumn(name="CAT")

    public class DomesticCat extends Cat {

        public String getName() { return name; }

    }

## 注意

The table name still defaults to the non qualified class name. Also if `@PrimaryKeyJoinColumn` is not set, the primary key / foreign key columns are assumed to have the same names as the primary key columns of the primary table of the superclass.

In hbm.xml, use the `<joined-subclass>` element. For example:

    <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>

| `name`：サブクラスの完全修飾されたクラス名。
| `table` :サブクラステーブルの名前。
| `proxy` (オプション): 遅延初期化プロキシに使用するクラスやインターフェースを指定します。
| `lazy` (オプション、デフォルトは `true` ): `lazy="false"` とすると、遅延フェッチが使用できません。

Use the `<key>` element to declare the primary key / foreign key column. The mapping at the start of the chapter would then be re-written as:

    <?xml version="1.0"?>

    <!DOCTYPE hibernate-mapping PUBLIC

            "-//Hibernate/Hibernate Mapping DTD//EN"

            "http://www.hibernate.org/dtd/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>

For information about inheritance mappings see 10章継承マッピング.

#### 5.1.6.3. Table per class strategy

A third option is to map only the concrete classes of an inheritance hierarchy to tables. This is called the table-per-concrete-class strategy. Each table defines all persistent states of the class, including the inherited state. In Hibernate, it is not necessary to explicitly map such inheritance hierarchies. You can map each class as a separate entity root. However, if you wish use polymorphic associations (e.g. an association to the superclass of your hierarchy), you need to use the union subclass mapping.

    @Entity

    @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)

    public class Flight implements Serializable { ... }

Or in hbm.xml:

    <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>

| `name`：サブクラスの完全修飾されたクラス名。
| `table` :サブクラステーブルの名前。
| `proxy` (オプション): 遅延初期化プロキシに使用するクラスやインターフェースを指定します。
| `lazy` (オプション、デフォルトは `true` ): `lazy="false"` とすると、遅延フェッチが使用できません。

このマッピング戦略では識別カラムやキーカラムは必要ありません。

For information about inheritance mappings see 10章継承マッピング.

#### 5.1.6.4. Inherit properties from superclasses

This is sometimes useful to share common properties through a technical or a business superclass without including it as a regular mapped entity (ie no specific table for this entity). For that purpose you can map them as `@MappedSuperclass`.

    @MappedSuperclass

    public class BaseEntity {

        @Basic

        @Temporal(TemporalType.TIMESTAMP)

        public Date getLastUpdate() { ... }

        public String getLastUpdater() { ... }

        ...

    }

    @Entity class Order extends BaseEntity {

        @Id public Integer getId() { ... }

        ...

    }

In database, this hierarchy will be represented as an `Order` table having the `id`, `lastUpdate` and `lastUpdater` columns. The embedded superclass property mappings are copied into their entity subclasses. Remember that the embeddable superclass is not the root of the hierarchy though.

## 注意

Properties from superclasses not mapped as `@MappedSuperclass` are ignored.

## 注意

The default access type (field or methods) is used, unless you use the `@Access` annotation.

## 注意

The same notion can be applied to `@Embeddable` objects to persist properties from their superclasses. You also need to use `@MappedSuperclass` to do that (this should not be considered as a standard EJB3 feature though)

## 注意

It is allowed to mark a class as `@MappedSuperclass` in the middle of the mapped inheritance hierarchy.

## 注意

Any class in the hierarchy non annotated with `@MappedSuperclass` nor `@Entity` will be ignored.

You can override columns defined in entity superclasses at the root entity level using the `@AttributeOverride` annotation.

    @MappedSuperclass

    public class FlyingObject implements Serializable {

        public int getAltitude() {

            return altitude;

        }

        @Transient

        public int getMetricAltitude() {

            return metricAltitude;

        }

        @ManyToOne

        public PropulsionType getPropulsion() {

            return metricAltitude;

        }

        ...

    }

    @Entity

    @AttributeOverride( name="altitude", column = @Column(name="fld_altitude") )

    @AssociationOverride(

       name="propulsion",

       joinColumns = @JoinColumn(name="fld_propulsion_fk")

    )

    public class Plane extends FlyingObject {

        ...

    }

The `altitude` property will be persisted in an `fld_altitude` column of table `Plane` and the propulsion association will be materialized in a `fld_propulsion_fk` foreign key column.

You can define `@AttributeOverride`(s) and `@AssociationOverride`(s) on `@Entity` classes, `@MappedSuperclass` classes and properties pointing to an `@Embeddable` object.

In hbm.xml, simply map the properties of the superclass in the `<class>` element of the entity that needs to inherit them.

#### 5.1.6.5. Mapping one entity to several tables

While not recommended for a fresh schema, some legacy databases force your to map a single entity on several tables.

Using the `@SecondaryTable` or `@SecondaryTables` class level annotations. To express that a column is in a particular table, use the `table` parameter of `@Column` or `@JoinColumn`.

    @Entity

    @Table(name="MainCat")

    @SecondaryTables({

        @SecondaryTable(name="Cat1", pkJoinColumns={

            @PrimaryKeyJoinColumn(name="cat_id", referencedColumnName="id")

        ),

        @SecondaryTable(name="Cat2", uniqueConstraints={@UniqueConstraint(columnNames={"storyPart2"})})

    })

    public class Cat implements Serializable {

        private Integer id;

        private String name;

        private String storyPart1;

        private String storyPart2;

        @Id @GeneratedValue

        public Integer getId() {

            return id;

        }

        public String getName() {

            return name;

        }

        @Column(table="Cat1")

        public String getStoryPart1() {

            return storyPart1;

        }

        @Column(table="Cat2")

        public String getStoryPart2() {

            return storyPart2;

        }

    }

In this example, `name` will be in `MainCat`. `storyPart1` will be in `Cat1` and `storyPart2` will be in `Cat2`. `Cat1` will be joined to `MainCat` using the `cat_id` as a foreign key, and `Cat2` using `id` (ie the same column name, the `MainCat` id column has). Plus a unique constraint on `storyPart2` has been set.

There is also additional tuning accessible via the `@org.hibernate.annotations.Table` annotation:

- `fetch`: If set to JOIN, the default, Hibernate will use an inner join to retrieve a secondary table defined by a class or its superclasses and an outer join for a secondary table defined by a subclass. If set to `SELECT` then Hibernate will use a sequential select for a secondary table defined on a subclass, which will be issued only if a row turns out to represent an instance of the subclass. Inner joins will still be used to retrieve a secondary defined by the class and its superclasses.

- `inverse`: If true, Hibernate will not try to insert or update the properties defined by this join. Default to false.

- `optional`: If enabled (the default), Hibernate will insert a row only if the properties defined by this join are non-null and will always use an outer join to retrieve the properties.

- `foreignKey`: defines the Foreign Key name of a secondary table pointing back to the primary table.

Make sure to use the secondary table name in the `appliesto` property

    @Entity

    @Table(name="MainCat")

    @SecondaryTable(name="Cat1")

    @org.hibernate.annotations.Table(

       appliesTo="Cat1",

       fetch=FetchMode.SELECT,

       optional=true)

    public class Cat implements Serializable {

        private Integer id;

        private String name;

        private String storyPart1;

        private String storyPart2;

        @Id @GeneratedValue

        public Integer getId() {

            return id;

        }

        public String getName() {

            return name;

        }

        @Column(table="Cat1")

        public String getStoryPart1() {

            return storyPart1;

        }

        @Column(table="Cat2")

        public String getStoryPart2() {

            return storyPart2;

        }

    }

In hbm.xml, use the `<join>` element.

    <join
            table="tablename"
            schema="owner"
            catalog="catalog"
            fetch="join|select"
            inverse="true|false"
            optional="true|false">

            <key ... />

            <property ... />
            ...
    </join>

| `table` :結合したテーブルの名前
| `schema` (オプション): ルートの `<hibernate-mapping>` 要素で指定したスキーマ名をオーバーライドします。
| `catalog` (オプション): ルートの `<hibernate-mapping>` 要素で指定したカタログ名をオーバーライドします。
| `fetch` (オプション - デフォルトは `join` ): `join` を設定した場合、 Hibernate はデフォルトで、クラスやスーパークラスで定義された `<join>` を検索するのに内部結合を使い、サブクラスで定義された `<join>` を検索するのに外部結合を使います。 `select` を設定した場合には、 Hibernate はサブクラスで定義された `<join>` の選択に順次選択を使います。この場合、行がサブクラスのインスタンスを代表することがわかった場合にのみ発行されます。内部結合はクラスやそのスーパークラスで定義された `<join>` を検索するために使用します。
| `inverse` (オプション - デフォルトは `false` ): もし可能であれば、 Hibernate はこの結合で定義されているプロパティに対し挿入や更新を行いません。
| `optional` (オプション - デフォルトは `false` ): もし可能であれば、 Hibernate はこの結合で定義されたプロパティが null でない場合にのみ行を挿入し、そのプロパティの検索には常に外部結合を使用します。

例えば人のアドレスの情報を分離したテーブルにマッピングすることが可能です (すべてのプロパティに対して値型のセマンティクスを保持します):

    <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>

        ...

この特徴はしばしばレガシーデータモデルに対してのみ有用ですが、クラスよりも少ないテーブルと、きめの細かいドメインモデルを推奨します。しかし後で説明するように、１つのクラス階層で継承のマッピング戦略を切り替える時には有用です。

### 5.1.7. Mapping one to one and one to many associations

To link one entity to an other, you need to map the association property as a to one association. In the relational model, you can either use a foreign key or an association table, or (a bit less common) share the same primary key value between the two entities.

To mark an association, use either `@ManyToOne` or `@OnetoOne`.

`@ManyToOne` and `@OneToOne` have a parameter named `targetEntity` which describes the target entity name. You usually don't need this parameter since the default value (the type of the property that stores the association) is good in almost all cases. However this is useful when you want to use interfaces as the return type instead of the regular entity.

Setting a value of the `cascade` attribute to any meaningful value other than nothing will propagate certain operations to the associated object. The meaningful values are divided into three categories.

1. basic operations, which include: `persist, merge, delete, save-update, evict, replicate, lock and refresh`;

2. special values: `delete-orphan` or `all` ;

3. comma-separated combinations of operation names: `cascade="persist,merge,evict"` or `cascade="all,delete-orphan"`. See 「連鎖的な永続化」 for a full explanation. Note that single valued many-to-one associations do not support orphan delete.

By default, single point associations are eagerly fetched in JPA 2. You can mark it as lazily fetched by using `@ManyToOne(fetch=FetchType.LAZY)` in which case Hibernate will proxy the association and load it when the state of the associated entity is reached. You can force Hibernate not to use a proxy by using `@LazyToOne(NO_PROXY)`. In this case, the property is fetched lazily when the instance variable is first accessed. This requires build-time bytecode instrumentation. lazy="false" specifies that the association will always be eagerly fetched.

With the default JPA options, single-ended associations are loaded with a subsequent select if set to `LAZY`, or a SQL JOIN is used for `EAGER` associations. You can however adjust the fetching strategy, ie how data is fetched by using `@Fetch`. `FetchMode` can be `SELECT` (a select is triggered when the association needs to be loaded) or `JOIN` (use a SQL JOIN to load the association while loading the owner entity). `JOIN` overrides any lazy attribute (an association loaded through a `JOIN` strategy cannot be lazy).

#### 5.1.7.1. Using a foreign key or an association table

An ordinary association to another persistent class is declared using a

- `@ManyToOne` if several entities can point to the the target entity

- `@OneToOne` if only a single entity can point to the the target entity

and a foreign key in one table is referencing the primary key column(s) of the target table.

    @Entity

    public class Flight implements Serializable {

        @ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} )

        @JoinColumn(name="COMP_ID")

        public Company getCompany() {

            return company;

        }

        ...

    }

The `@JoinColumn` attribute is optional, the default value(s) is the concatenation of the name of the relationship in the owner side, _ (underscore), and the name of the primary key column in the owned side. In this example `company_id` because the property name is `company` and the column id of Company is `id`.

    @Entity

    public class Flight implements Serializable {

        @ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE}, targetEntity=CompanyImpl.class )

        @JoinColumn(name="COMP_ID")

        public Company getCompany() {

            return company;

        }

        ...

    }

    public interface Company {

        ...

    }

You can also map a to one association through an association table. This association table described by the `@JoinTable` annotation will contains a foreign key referencing back the entity table (through `@JoinTable.joinColumns`) and a a foreign key referencing the target entity table (through `@JoinTable.inverseJoinColumns`).

    @Entity

    public class Flight implements Serializable {

        @ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} )

        @JoinTable(name="Flight_Company",

            joinColumns = @JoinColumn(name="FLIGHT_ID"),

            inverseJoinColumns = @JoinColumn(name="COMP_ID")

        )

        public Company getCompany() {

            return company;

        }

        ...

    }

## 注意

You can use a SQL fragment to simulate a physical join column using the `@JoinColumnOrFormula` / `@JoinColumnOrformulas` annotations (just like you can use a SQL fragment to simulate a property column via the `@Formula` annotation).

    @Entity

    public class Ticket implements Serializable {

        @ManyToOne

        @JoinColumnOrFormula(formula="(firstname + ' ' + lastname)")

        public Person getOwner() {

            return person;

        }

        ...

    }

You can mark an association as mandatory by using the `optional=false` attribute. We recommend to use Bean Validation's `@NotNull` annotation as a better alternative however. As a consequence, the foreign key column(s) will be marked as not nullable (if possible).

When Hibernate cannot resolve the association because the expected associated element is not in database (wrong id on the association column), an exception is raised. This might be inconvenient for legacy and badly maintained schemas. You can ask Hibernate to ignore such elements instead of raising an exception using the `@NotFound` annotation.

例5.1 @NotFound annotation

    @Entity

    public class Child {

        ...

        @ManyToOne

        @NotFound(action=NotFoundAction.IGNORE)

        public Parent getParent() { ... }

        ...

    }

Sometimes you want to delegate to your database the deletion of cascade when a given entity is deleted. In this case Hibernate generates a cascade delete constraint at the database level.

例5.2 @OnDelete annotation

    @Entity

    public class Child {

        ...

        @ManyToOne

        @OnDelete(action=OnDeleteAction.CASCADE)

        public Parent getParent() { ... }

        ...

    }

Foreign key constraints, while generated by Hibernate, have a fairly unreadable name. You can override the constraint name using `@ForeignKey`.

例5.3 @ForeignKey annotation

    @Entity

    public class Child {

        ...

        @ManyToOne

        @ForeignKey(name="FK_PARENT")

        public Parent getParent() { ... }

        ...

    }

    alter table Child add constraint FK_PARENT foreign key (parent_id) references Parent

Sometimes, you want to link one entity to an other not by the target entity primary key but by a different unique key. You can achieve that by referencing the unique key column(s) in `@JoinColumn.referenceColumnName`.

    @Entity

    class Person {

       @Id Integer personNumber;

       String firstName;

       @Column(name="I")

       String initial;

       String lastName;

    }

    @Entity

    class Home {

       @ManyToOne

       @JoinColumns({

          @JoinColumn(name="first_name", referencedColumnName="firstName"),

          @JoinColumn(name="init", referencedColumnName="I"),

          @JoinColumn(name="last_name", referencedColumnName="lastName"),

       })

       Person owner

    }

This is not encouraged however and should be reserved to legacy mappings.

In hbm.xml, mapping an association is similar. The main difference is that a `@OneToOne` is mapped as `<many-to-one unique="true"/>`, let's dive into the subject.

    <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"
    />

| `name`：プロパティ名。
| `column` (オプション):外部キーカラムの名前。ネストした `<column>` カラムによっても指定されます。
| `class`（オプション - デフォルトはリフレクションにより決定されるプロパティの型）： 関連クラスの名前。
| `cascade`（オプション）： 親オブジェクトから関連オブジェクトへ、どの操作をカスケードするかを指定します。
| `fetch`（オプション - デフォルトは `select` ）： 外部結合フェッチと順次選択フェッチ（sequential select fetch）のどちらかを選択します。
| `update, insert`（オプション - デフォルトは `true` ）： マッピングされたカラムが SQL の `UPDATE` または `INSERT` 文に含まれることを指定します。両方とも `false` に設定すると、その値が同じカラムにマッピングされた他のプロパティやトリガや他のアプリケーションによって初期化された純粋な「導出」プロパティが可能になります。
| `property-ref`: (オプション) この外部キーに加わる、関連クラスのプロパティの名前。指定されていない場合は、関連クラスの主キーが使用されます。
| `access` (オプション - デフォルトは `property` ): Hibernate がプロパティの値にアクセスするために使用すべき戦略。
| `unique`（オプション）： 外部キーカラムに対してユニーク制約をつけた DDL の生成を可能にします。また、 `property-ref` のターゲットにすることもできます。これにより関連の多重度を効果的に一対一にします。
| `not-null` (オプション): 外部キーカラムに対して、 null 値を許可する DDL の生成を可能にします。
| `optimistic-lock` (オプション - デフォルトは `true` ): このプロパティの更新に楽観ロックの取得を要求するかどうかを指定します。言い換えれば、このプロパティがダーティであるときにバージョンを増やすべきかを決定します。
| `lazy` (オプション - デフォルトは `proxy` ): デフォルトでは、多重度１の関連がプロキシとなります。 `lazy="no-proxy"` は、インスタンス変数に最初にアクセスしたときに、プロパティを遅延フェッチするよう指定します (ビルド時にバイトコード実装が必要になります)。 `lazy="false"` は関連を常に即時にフェッチするよう指定します。
| `not-found` （オプション - デフォルトは `exception`）: 参照先の行がない外部キーをどのように扱うかを指定します: `ignore` を指定すると、行がないことを関連がないものとして扱います。
| `entity-name` (オプション):関連したクラスのエンティティ名。
| `formula` (オプション): 計算された 外部キーに対して値を定義する SQL 式

Setting a value of the `cascade` attribute to any meaningful value other than `none` will propagate certain operations to the associated object. The meaningful values are divided into three categories. First, basic operations, which include: `persist, merge, delete, save-update, evict, replicate, lock and refresh`; second, special values: `delete-orphan`; and third,`all` comma-separated combinations of operation names: `cascade="persist,merge,evict"` or `cascade="all,delete-orphan"`. See 「連鎖的な永続化」 for a full explanation. Note that single valued, many-to-one and one-to-one, associations do not support orphan delete.

典型的な `many-to-one` 宣言は次のようにシンプルです。：

    <many-to-one name="product" class="Product" column="PRODUCT_ID"/>

`property-ref` 属性は、外部キーが関連付けられたテーブルの、主キーでないユニークキーを参照しているレガシーデータをマップするためにだけ使うべきです。これは醜いリレーショナルモデルです。例えば `Product` クラスが、主キーでないユニークなシリアルナンバーを持っていると仮定してみてください。（ `unique` 属性は SchemaExport ツールを使った Hibernate の DDL 生成を制御します。）

    <property name="serialNumber" unique="true" type="string" column="SERIAL_NUMBER"/>

以下のように `OrderItem` に対してマッピングを使えます：

    <many-to-one name="product" property-ref="serialNumber" column="PRODUCT_SERIAL_NUMBER"/>

しかし、これは決して推奨できません。

参照したユニークキーが、関連するエンティティの多数のプロパティから構成される場合、指定した `<properties>` 要素内で、参照するプロパティをマッピングするべきです。

もし参照したユニークキーがコンポーネントのプロパティである場合は、プロパティのパスを指定できます:

    <many-to-one name="owner" property-ref="identity.ssn" column="OWNER_SSN"/>

#### 5.1.7.2. Sharing the primary key with the associated entity

The second approach is to ensure an entity and its associated entity share the same primary key. In this case the primary key column is also a foreign key and there is no extra column. These associations are always one to one.

例5.4 One to One association

    @Entity

    public class Body {

        @Id

        public Long getId() { return id; }

        @OneToOne(cascade = CascadeType.ALL)

        @MapsId

        public Heart getHeart() {

            return heart;

        }

        ...

    }

    @Entity

    public class Heart {

        @Id

        public Long getId() { ...}

    }

## 注意

Many people got confused by these primary key based one to one associations. They can only be lazily loaded if Hibernate knows that the other side of the association is always present. To indicate to Hibernate that it is the case, use `@OneToOne(optional=false)`.

In hbm.xml, use the following mapping.

    <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"
    />

| `name`：プロパティ名。
| `class`（オプション - デフォルトはリフレクションにより決定されるプロパティの型）： 関連クラスの名前。
| `cascade`（オプション）： 親オブジェクトから関連オブジェクトへ、どの操作をカスケードするかを指定します。
| `constrained`（オプション）： マッピングされたテーブルの主キーに対する外部キー制約が、関連クラスのテーブルを参照することを指定します。このオプションは `save()` と `delete()` がカスケードされる順序に影響し、そして関連がプロキシされるかどうかにも影響します （そしてスキーマエクスポートツールにも使われます）。
| `fetch`（オプション - デフォルトは `select` ）： 外部結合フェッチと順次選択フェッチ（sequential select fetch）のどちらかを選択します。
| `property-ref`（オプション）： このクラスの主キーに結合された関連クラスのプロパティ名。指定されなければ、関連クラスの主キーが使われます。
| `access` (オプション - デフォルトは `property` ): Hibernate がプロパティの値にアクセスするために使用すべき戦略。
| `formula` (オプション): ほとんどすべての一対一関連はオーナーのエンティティの主キーへとマッピングされます。これ以外の稀な場合は、他のカラムや、複数のカラム、 SQL 構文を使った結合するための式を指定できます。（例は `org.hibernate.test.onetooneformula` を参照してください。）
| `lazy` (オプション - デフォルトは `proxy` ): デフォルトでは、多重度１の関連がプロキシとなります。 `lazy="no-proxy"` は、インスタンス変数に最初にアクセスしたときに、プロパティを遅延フェッチするよう指定します (ビルド時にバイトコード実装が必要になります)。 `lazy="false"` は関連を常に即時にフェッチするよう指定します。 もし `constrained="false"` ならば、プロキシは使用不可能となり、関連を即時にフェッチすることに注意してください。
| `entity-name` (オプション):関連したクラスのエンティティ名。

主キー関連には、特別なテーブルカラムは必要ありません。もし2つの行が関連により関係していれば、2つのテーブルは同じ主キーの値を共有します。そのため2つのオブジェクトを主キー関連によって関連付けたいのであれば、確実に同じ識別子の値を代入しなければなりません。

主キー関連を行うためには、以下のマッピングを `Employee` と `Person` のそれぞれに追加してください。

    <one-to-one name="person" class="Person"/>

    <one-to-one name="employee" class="Employee" constrained="true"/>

ここで、 PERSON と EMPLOYEE テーブルの関係する行の主キーが同じであることを確実にしなければいけません。ここでは、 `foreign` という特殊な Hibernate 識別子生成戦略を使います：

    <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>

`Employee` インスタンスが、 `Person` の `employee` プロパティで参照されるように、新しくセーブされた `Person` のインスタンスには同じ主キーの値が代入されます。新しくセーブする `Person` インスタンスは、その `Person` の `employee` プロパティが参照する `Employee` インスタンスとして同じ主キーが割り当てられます。

### 5.1.8. natural-id

Although we recommend the use of surrogate keys as primary keys, you should try to identify natural keys for all entities. A natural key is a property or combination of properties that is unique and non-null. It is also immutable. Map the properties of the natural key as `@NaturalId` or map them inside the `<natural-id>` element. Hibernate will generate the necessary unique key and nullability constraints and, as a result, your mapping will be more self-documenting.

    @Entity

    public class Citizen {

        @Id

        @GeneratedValue

        private Integer id;

        private String firstname;

        private String lastname;

        @NaturalId

        @ManyToOne

        private State state;

        @NaturalId

        private String ssn;

        ...

    }

    //and later on query

    List results = s.createCriteria( Citizen.class )

                    .add( Restrictions.naturalId().set( "ssn", "1234" ).set( "state", ste ) )

                    .list();

Or in XML,

    <natural-id mutable="true|false"/>

            <property ... />

            <many-to-one ... />

            ......

    </natural-id>

エンティティの自然キープロパティの比較には、 `equals()` と `hashCode()` の実装を強くお勧めします。

このマッピングは自然主キーを使ったエンティティでの使用を意図していません。

- `mutable` (オプション、 デフォルトは `false` ): デフォルトでは、自然識別子プロパティは不変(定数)と想定されています。

### 5.1.9. Any

There is one more type of property mapping. The `@Any` mapping defines a polymorphic association to classes from multiple tables. This type of mapping requires more than one column. The first column contains the type of the associated entity. The remaining columns contain the identifier. It is impossible to specify a foreign key constraint for this kind of association. This is not the usual way of mapping polymorphic associations and you should use this only in special cases. For example, for audit logs, user session data, etc.

The `@Any` annotation describes the column holding the metadata information. To link the value of the metadata information and an actual entity type, The `@AnyDef` and `@AnyDefs` annotations are used. The `metaType` attribute allows the application to specify a custom type that maps database column values to persistent classes that have identifier properties of the type specified by `idType`. You must specify the mapping from values of the `metaType` to class names.

    @Any( metaColumn = @Column( name = "property_type" ), fetch=FetchType.EAGER )

    @AnyMetaDef(

        idType = "integer",

        metaType = "string",

        metaValues = {

            @MetaValue( value = "S", targetEntity = StringProperty.class ),

            @MetaValue( value = "I", targetEntity = IntegerProperty.class )

        } )

    @JoinColumn( name = "property_id" )

    public Property getMainProperty() {

        return mainProperty;

    }

Note that `@AnyDef` can be mutualized and reused. It is recommended to place it as a package metadata in this case.

    //on a package

    @AnyMetaDef( name="property"

        idType = "integer",

        metaType = "string",

        metaValues = {

            @MetaValue( value = "S", targetEntity = StringProperty.class ),

            @MetaValue( value = "I", targetEntity = IntegerProperty.class )

        } )

    package org.hibernate.test.annotations.any;

    //in a class

        @Any( metaDef="property", metaColumn = @Column( name = "property_type" ), fetch=FetchType.EAGER )

        @JoinColumn( name = "property_id" )

        public Property getMainProperty() {

            return mainProperty;

        }

The hbm.xml equivalent is:

    <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>

## 注意

You cannot mutualize the metadata in hbm.xml as you can in annotations.

    <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>

| `name`： プロパティ名。
| `id-type`： 識別子の型。
| `meta-type`（オプション - デフォルトは `string` ）： ディスクリミネータマッピングで許された型。
| `cascade`（オプション - デフォルトは `none` ）： カスケードのスタイル。
| `access` (オプション - デフォルトは `property` ): Hibernate がプロパティの値にアクセスするために使用すべき戦略。
| `optimistic-lock` (オプション - デフォルトは `true` ): このプロパティの更新に楽観ロックの取得を要求するかどうかを指定します。言い換えれば、このプロパティがダーティであるときにバージョンを増やすべきかを定義します。

### 5.1.10. プロパティ

`<properties>` 要素はクラスのプロパティの指定された、論理的なグルーピングを可能にします。この構造の最も重要な使用方法は、 `property-ref` のターゲットになるプロパティの結合を許可することです。それはまた、複数カラムのユニーク制約を定義する簡単な方法でもあります。

    <properties
            name="logicalName"
            insert="true|false"
            update="true|false"
            optimistic-lock="true|false"
            unique="true|false"
    >

            <property ...../>
            <many-to-one .... />
            ........
    </properties>

| `name` : グルーピングの論理名。実際のプロパティ名では ありません 。
| `insert`：マッピングされたカラムが SQL の `INSERT` に現れるようにするかどうかを指定します。
| `update`：マッピングされたカラムが SQL の `UPDATE` に現れるようにするかどうかを指定します。
| `optimistic-lock` (オプション - デフォルトは `true` ): これらのプロパティの更新に楽観的ロックの取得を要求するかどうかを指定します。言い換えれば、このプロパティがダーティであるときにバージョンを増やすべきかを決定します。
| `unique` (オプション - デフォルトは `false` ): コンポーネントのすべてのマッピングするカラムに、ユニーク制約が存在するかを指定します。

例えば、もし以下のような `<properties>` マッピングがあった場合：

    <class name="Person">

        <id name="personNumber"/>

        ...

        <properties name="name"

                unique="true" update="false">

            <property name="firstName"/>

            <property name="initial"/>

            <property name="lastName"/>

        </properties>

    </class>

主キーの代わりに `Person` テーブルのユニークキーへの参照を持つ、レガシーデータの関連を持つかもしれません。：

    <many-to-one name="owner"

             class="Person" property-ref="name">

        <column name="firstName"/>

        <column name="initial"/>

        <column name="lastName"/>

    </many-to-one>

## 注意

When using annotations as a mapping strategy, such construct is not necessary as the binding between a column and its related column on the associated table is done directly

    @Entity

    class Person {

       @Id Integer personNumber;

       String firstName;

       @Column(name="I")

       String initial;

       String lastName;

    }

    @Entity

    class Home {

       @ManyToOne

       @JoinColumns({

          @JoinColumn(name="first_name", referencedColumnName="firstName"),

          @JoinColumn(name="init", referencedColumnName="I"),

          @JoinColumn(name="last_name", referencedColumnName="lastName"),

       })

       Person owner

    }

しかし、このようなレガシーデータマッピングのコンテキスト外への使用は推奨しません。

### 5.1.11. Some hbm.xml specificities

The hbm.xml structure has some specificities naturally not present when using annotations, let's describe them briefly.

#### 5.1.11.1. Doctype

XML マッピングでは、お見せしたようなドキュメント型を必ず定義すべきです。実際の DTD は、上記の URL の `hibernate-x.x.x/src/org/hibernate` ディレクトリ、または `hibernate.jar` 内にあります。 Hibernate は常に、そのクラスパス内で DTD を探し始めます。インターネットにある DTD ファイルを探そうとしたなら、クラスパスの内容を見て、 DTD 宣言を確認してください。

##### 5.1.11.1.1. エンティティリゾルバ

前述したように、 Hibernate はまずクラスパス内で DTD を解決しようとします。 `org.xml.sax.EntityResolver` のカスタム実装を XML ファイルを読み込むための SAXReader に登録することによって、 DTD を解決します。このカスタムの `EntityResolver` は2つの異なるシステム ID 名前空間を認識します。

- a `hibernate namespace` is recognized whenever the resolver encounters a systemId starting with `http://www.hibernate.org/dtd/`. The resolver attempts to resolve these entities via the classloader which loaded the Hibernate classes.

- `user namespace` は、リゾルバが URL プロトコルの `classpath://` を使ったシステム ID に到達したときに、認識されます。そしてリゾルバは、 (1) カレントスレッドのコンテキストクラスローダー、または (2) Hibernate のクラスをロードしたクラスローダを使って、これらのエンティティを解決しようとします。

下記は、ユーザー名前空間を使った例です：

    <?xml version="1.0"?>

    <!DOCTYPE hibernate-mapping PUBLIC

            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

            "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" [

        <!ENTITY types SYSTEM "classpath://your/domain/types.xml">

    ]>

    <hibernate-mapping package="your.domain">

        <class name="MyEntity">

            <id name="id" type="my-custom-id-type">

                ...

            </id>

        <class>

        &types;

    </hibernate-mapping>

Where `types.xml` is a resource in the `your.domain` package and contains a custom typedef.

#### 5.1.11.2. Hibernate-mapping

この要素にはいくつかオプション属性があります。 `schema` 属性と `catalog` 属性は、このマッピングが参照するテーブルが、この属性によって指定されたスキーマと(または)カタログに属することを指定します。この属性が指定されると、テーブル名は与えられたスキーマ名とカタログ名で修飾されます。これらの属性が指定されていなければ、テーブル名は修飾されません。 `default-cascade` 属性は、 `cascade` 属性を指定していないプロパティやコレクションに、どのカスケードスタイルを割り当てるかを指定します。 `auto-import` 属性は、クエリ言語内で修飾されていないクラス名を、デフォルトで使えるようにします。

    <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"
     />

| `schema`（オプション）：データベーススキーマの名前。
| `catalog` （オプション）：データベースカタログの名前。
| `default-cascade` （オプション - デフォルトは `none`）： デフォルトのカスケードスタイル。
| `default-access` (オプション - デフォルトは `property` ）： Hibernate がプロパティにアクセスする際に取るべき戦略。 `PropertyAccessor` を実装することでカスタマイズ可能。
| `default-lazy` (オプション - デフォルトは `true` )： `lazy` 属性が指定されていないクラスやコレクションマッピングに対するデフォルト値。
| `auto-import` （オプション - デフォルトは `true`）：クエリ言語内で、（このマッピング内のクラスの）修飾されていないクラス名を使えるかどうかを指定します。
| `package` (オプション): マッピングドキュメント内で修飾されていないクラス名に対して割り当てる、パッケージの接頭辞 (prefix) を指定します。

（修飾されていない）同じ名前の永続クラスが2つあるなら、 `auto-import="false"` を設定すべきです。2つのクラスに"インポートされた"同じ名前を割り当てようとすると、 Hibernate は例外を送出します。

`hibernate-mapping` 要素は、最初の例で示したようにいくつかの永続 `<class>` マッピングをネストできます。しかし、１つのマッピングファイルではただひとつの永続クラス(またはひとつのクラス階層)にマッピングするようにし、さらに永続スーパークラスの後で指定するべきでしょう(いくつかのツールはこのようなマッピングファイルを想定しています)。例えば次のようになります。： `Cat.hbm.xml` , `Dog.hbm.xml` , または継承を使うなら `Animal.hbm.xml` 。

#### 5.1.11.3. Key

The `<key>` element is featured a few times within this guide. It appears anywhere the parent mapping element defines a join to a new table that references the primary key of the original table. It also defines the foreign key in the joined table:

    <key
            column="columnname"
            on-delete="noaction|cascade"
            property-ref="propertyName"
            not-null="true|false"
            update="true|false"
            unique="true|false"
    />

| `column` (オプション):外部キーカラムの名前。ネストした `<column>` カラムによっても指定されます。
| `on-delete` (オプション, デフォルトは `noaction`): 外部キー制約がデータベースレベルでカスケード削除が可能かどうかを指定します。
| `property-ref` (オプション): オリジナルテーブルの主キーではないカラムを参照する外部キーを指定します (レガシーデータに対して提供されます)。
| `not-null` (オプション): 外部キーカラムが null 値を許容しないことを指定します (このことは外部キーが主キーの一部であることを暗黙的に示します)。
| `update` (オプション): 外部キーを決して更新してはならないことを指定します (このことは外部キーが主キーの一部であることを暗黙的に示します)。
| `unique` (オプション): 外部キーがユニーク制約を持つべきであることを指定します (このことは外部キーが主キーの一部であることを暗黙的に示します)。

削除のパフォーマンスが重要であるシステムには、すべてのキーを `on-delete="cascade"` と定義することを推奨します。そうすることで Hibernate は、 `DELETE` 文を毎回発行する代わりに、データベースレベルの `ON CASCADE DELETE` 制約を使用します。この特徴はバージョン付けられたデータに対する Hibernate の通常の楽観的ロック戦略を無視するということに注意してください。

`not-null` と `update` 属性は、単方向一対多関連の時には有用です。単方向一対多関連を null を許容しない外部キーにマッピングするときは、 `<key not-null="true">` を使ってキーカラムを宣言 しなくてはなりません 。

#### 5.1.11.4. Import

アプリケーションに同じ名前の2つの永続クラスがあり、 Hibernate クエリで完全修飾された（パッケージの）名前を指定したくないと仮定します。そのような場合は `auto-import="true"` に頼らず、クラスが「インポート」されたものであると明示できます。明示的にマッピングされていないクラスやインターフェースでさえもインポートできます。

    <import class="java.lang.Object" rename="Universe"/>

    <import
            class="ClassName"
            rename="ShortName"
    />

| `class`： Java クラスの完全修飾されたクラス名。
| `rename` （オプション - デフォルトは修飾されていないクラス名）： クエリ言語で使われる名前。

## 注意

This feature is unique to hbm.xml and is not supported in annotations.

#### 5.1.11.5. column と formula 要素

`column` 属性を記述できる任意のマッピング要素はまた、 `<column>` サブ要素も記述できます。同様に `<formula>` も `formula` 属性の代替手段です。

    <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"

            read="SQL expression"

            write="SQL expression"/>

    <formula>SQL expression</formula>

Most of the attributes on `column` provide a means of tailoring the DDL during automatic schema generation. The `read` and `write` attributes allow you to specify custom SQL that Hibernate will use to access the column's value. For more on this, see the discussion of column read and write expressions.

The `column` and `formula` elements can even be combined within the same property or association mapping to express, for example, exotic join conditions.

    <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>

## 5.2. Hibernate の型

### 5.2.1. エンティティと値

In relation to the persistence service, Java language-level objects are classified into two groups:

エンティティ はエンティティへの参照を保持する、他のすべてのオブジェクトから独立して存在します。参照されないオブジェクトがガベージコレクトされてしまう性質を持つ通常の Java モデルと、これを比べてみてください。（親エンティティから子へ、セーブと削除が カスケード されうることを除いて）エンティティは明示的にセーブまたは削除されなければなりません。これは到達可能性によるオブジェクト永続化の ODMG モデルとは異なっています。大規模なシステムでアプリケーションオブジェクトが普通どのように使われるかにより密接に対応します。エンティティは循環と参照の共有をサポートします。またそれらはバージョン付けすることもできます。

エンティティの永続状態は他のエンティティや 値 型のインスタンスへの参照から構成されます。値はプリミティブ、コレクション (コレクションの内部ではなく)、コンポーネント、不変オブジェクトです。エンティティとは違い、値は（特にコレクションとコンポーネントにおいて）、到達可能性による永続化や削除が 行われます 。値オブジェクト（とプリミティブ）は、包含するエンティティと一緒に永続化や削除が行われるので、それらを独立にバージョン付けすることはできません。値には独立したアイデンティティがないので、複数のエンティティやコレクションがこれを共有することはできません。

これまで「永続クラス」という言葉をエンティティの意味で使ってきました。これからもそうしていきます。厳密に言うと、永続状態を持つユーザー定義のクラスのすべてがエンティティというわけではありません。 コンポーネント は値のセマンティクスを持つユーザー定義クラスです。 `java.lang.String` 型のプロパティもまた値のセマンティクスを持ちます。定義するなら、 JDK で提供されているすべての Java の型 (クラス) が値のセマンティクスを持つといえます。一方ユーザー定義型は、エンティティや値型のセマンティクスとともにマッピングできます。この決定はアプリケーション開発者次第です。そのクラスの１つのインスタンスへの共有参照は、ドメインモデル内のエンティティクラスに対する良いヒントになります。一方合成集約や集約は、通常値型へ変換されます。

本ドキュメントを通して、何度もこの概念を取り上げます。

Java 型のシステム (もしくは開発者が定義したエンティティと値型) を SQL /データベース型のシステムにマッピングすることは難しいです。 Hibernate は２つのシステムの架け橋を提供します。エンティティに対しては `<class>` や `<subclass>` などを使用します。値型に対しては `<property>` や `<component>` などを、通常 `type` と共に使います。この属性の値は Hibernate の マッピング型 の名前です。 Hibernate は (標準 JDK の値型に対して) 多くの自由なマッピングを提供します。後で見るように、自身のマッピング型を記述し、同様にカスタムの変換戦略を実装することができます。

コレクションを除く組み込みの Hibernate の型はすべて、 null セマンティクスをサポートします。

### 5.2.2. 基本的な型

組み込みの 基本的なマッピング型 は大まかに以下のように分けられます。

`integer, long, short, float, double, character, byte, boolean, yes_no, true_false`

  Java のプリミティブやラッパークラスから適切な（ベンダー固有の） SQL カラム型への型マッピング。 `boolean, yes_no` と `true_false` は、すべて Java の `boolean` または `java.lang.Boolean` の代替エンコードです。

`string`

  `java.lang.String` から `VARCHAR` （または Oracle の `VARCHAR2` ）への型マッピング。

`date, time, timestamp`

  `java.util.Date` とそのサブクラスから SQL 型の `DATE` 、 `TIME` 、 `TIMESTAMP` （またはそれらと等価なもの） への型マッピング。

`calendar, calendar_date`

  `java.util.Calendar` から SQL 型 の「 `TIMESTAMP` 、 `DATE` (またはそれらと等価なもの）への型マッピング。

`big_decimal, big_integer`

  `java.math.BigDecimal` と `java.math.BigInteger` から `NUMERIC`（または Oracle の `NUMBER` ）への型マッピング。

`locale, timezone, currency`

  `java.util.Locale` 、 `java.util.TimeZone` 、 `java.util.Currency` から `VARCHAR` （または Oracle の `VARCHAR2` ）への型マッピング。 `Locale` と `Currency` のインスタンスは、それらの ISO コードにマッピングされます。 `TimeZone` のインスタンスは、それらの `ID` にマッピングされます。

`class`

  `java.lang.Class` から `VARCHAR` （または Oracle の `VARCHAR2` ）への型マッピング。 `Class` はその完全修飾された名前にマッピングされます。

`binary`

  バイト配列は、適切な SQL のバイナリ型にマッピングされます。

`text`

  Maps long Java strings to a SQL `LONGVARCHAR` or `TEXT` type.

`image`

  Maps long byte arrays to a SQL `LONGVARBINARY`.

`serializable`

  シリアライズ可能な Java 型は、適切な SQL のバイナリ型にマッピングされます。デフォルトで基本型ではないシリアライズ可能な Java クラスやインターフェースの名前を指定することで、 Hibernate の型を `serializable` とすることもできます。

`clob, blob`

  JDBC クラス `java.sql.Clob` と `java.sql.Blob` に対する型マッピング。 blob や clob オブジェクトはトランザクションの外では再利用できないため、アプリケーションによっては不便かもしれません。（さらにはドライバサポートが一貫していません。）

`materialized_clob`

  Maps long Java strings to a SQL `CLOB` type. When read, the `CLOB` value is immediately materialized into a Java string. Some drivers require the `CLOB` value to be read within a transaction. Once materialized, the Java string is available outside of the transaction.

`materialized_blob`

  Maps long Java byte arrays to a SQL `BLOB` type. When read, the `BLOB` value is immediately materialized into a byte array. Some drivers require the `BLOB` value to be read within a transaction. Once materialized, the byte array is available outside of the transaction.

`imm_date, imm_time, imm_timestamp, imm_calendar, imm_calendar_date, imm_serializable, imm_binary`

  ほとんどの場合に可変である Java の型に対する型マッピング。 Hibernate は不変な Java の型に対しては最適化を行い、アプリケーションはそれを不変オブジェクトとして扱います。例えば `imm_timestamp` としてマップしたインスタンスに対して、 `Date.setTime()` を呼び出してはなりません。プロパティの値を変更しその変更を永続化するためには、アプリケーションはプロパティに対して新しい (同一でない) オブジェクトを割り当てなければなりません。

エンティティとコレクションのユニークな識別子は、 `binary` 、 `blob` 、 `clob` を除く、どんな基本型でも構いません。（複合識別子でも構いません。以下を見てください。）

基本的な値型には、 `org.hibernate.Hibernate` で定義された `Type` 定数がそれぞれあります。例えば、 `Hibernate.STRING` は `string` 型を表現しています。

### 5.2.3. カスタム型

開発者が独自の値型を作成することは、比較的簡単です。例えば、 `java.lang.BigInteger` 型のプロパティを `VARCHAR` カラムに永続化したいかもしれません。 Hibernate はこのための組み込み型を用意していません。しかしカスタム型は、プロパティ（またはコレクションの要素）を1つのテーブルカラムにマッピングするのに制限はありません。そのため例えば、 `java.lang.String` 型の `getName()` / `setName()` Java プロパティを `FIRST_NAME` 、 `INITIAL` 、 `SURNAME` カラムに永続化できます。

カスタム型を実装するには、 `org.hibernate.UserType` または `org.hibernate.CompositeUserType` を実装し、型の完全修飾された名前を使ってプロパティを定義します。どのような種類のものが可能かを調べるには、 `org.hibernate.test.DoubleStringType` を確認してください。

    <property name="twoStrings" type="org.hibernate.test.DoubleStringType">

        <column name="first_string"/>

        <column name="second_string"/>

    </property>

`<column>` タグで、プロパティを複数のカラムへマッピングできることに注目してください。

`CompositeUserType` 、 `EnhancedUserType` 、 `UserCollectionType` 、 `UserVersionType` インターフェースは、より特殊な使用法に対してのサポートを提供します。

マッピングファイル内で `UserType` へパラメータを提供できます。このためには、 `UserType` は `org.hibernate.usertype.ParameterizedType` を実装しなくてはなりません。カスタム型パラメータを提供するために、マッピングファイル内で `<type>` 要素を使用できます。

    <property name="priority">

        <type name="com.mycompany.usertypes.DefaultValueIntegerType">

            <param name="default">0</param>

        </type>

    </property>

`UserType` は、引数として渡された `Properties` オブジェクトから、 `default` で指定したパラメータに対する値を検索することができます。

特定の `UserType` を頻繁に使用するならば、短い名前を定義すると便利になるでしょう。 `<typedef>` 要素を使ってこのようなことが行えます。 Typedefs はカスタム型に名前を割り当てます。その型がパラメータを持つならば、パラメータのデフォルト値のリストを含むこともできます。

    <typedef class="com.mycompany.usertypes.DefaultValueIntegerType" name="default_zero">

        <param name="default">0</param>

    </typedef>

    <property name="priority" type="default_zero"/>

プロパティのマッピングで型パラメータを使うことで、 typedef で提供されたパラメータをその都度オーバーライドすることが可能です。

Even though Hibernate's rich range of built-in types and support for components means you will rarely need to use a custom type, it is considered good practice to use custom types for non-entity classes that occur frequently in your application. For example, a `MonetaryAmount` class is a good candidate for a `CompositeUserType`, even though it could be mapped as a component. One reason for this is abstraction. With a custom type, your mapping documents would be protected against changes to the way monetary values are represented.

## 5.3. １つのクラスに１つ以上のマッピング

ある永続クラスに、一つ以上のマッピングを提供することが出来ます。この場合、マッピングする２つのエンティティのインスタンスを明確にするために、 エンティティ名 を指定しなければなりません (デフォルトではエンティティ名はクラス名と同じです。)。 Hibernate では、永続オブジェクトを扱うとき、クエリを書き込むとき、指定されたエンティティへの関連をマッピングするときに、エンティティ名を指定しなければなりません。

    <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>

関連が `class` の代わりに `entity-name` を使って、どのように指定されるのかに注目してください。

## 注意

This feature is not supported in Annotations

## 5.4. バッククォートで囲んだ SQL 識別子

マッピングドキュメントでテーブルやカラムの名前をバッククォートで囲むことで、 Hibernate で生成された SQL 中の識別子を引用させることができます。 Hibernate は SQL の `Dialect` に対応する、正しい引用スタイルを使います（普通はダブルクォートですが、 SQL Server ではかぎ括弧、 MySQL ではバッククォートです）。

    @Entity @Table(name="`Line Item`")

    class LineItem {

       @id @Column(name="`Item Id`") Integer id;

       @Column(name="`Item #`") int itemNumber

    }

    <class name="LineItem" table="`Line Item`">

        <id name="id" column="`Item Id`"/><generator class="assigned"/></id>

        <property name="itemNumber" column="`Item #`"/>

        ...

    </class>

## 5.5. 生成プロパティ

生成プロパティとは、データベースによって生成された値を持つプロパティです。通常、 Hibernate アプリケーションは、データベースが値を生成したプロパティを含むオブジェクトを `リフレッシュ` する必要がありました。しかし、プロパティが生成されたということをマークすることで、アプリケーションはリフレッシュの責任を Hibernate に委譲します。基本的に、生成プロパティを持つと定義したエンティティに対して Hibernate が INSERT や UPDATE の SQL を発行した後すぐに、生成された値を読み込むための SELECT SQL が発行されます。

Properties marked as generated must additionally be non-insertable and non-updateable. Only versions, timestamps, and simple properties, can be marked as generated.

`never` (デフォルト) - 与えられたプロパティの値は、データベースから生成されないことを意味します。

`insert`: the given property value is generated on insert, but is not regenerated on subsequent updates. Properties like created-date fall into this category. Even though version and timestamp properties can be marked as generated, this option is not available.

`always` - 挿入時も更新時もプロパティの値が生成されることを示します。

To mark a property as generated, use `@Generated`.

## 5.6. Column transformers: read and write expressions

Hibernate allows you to customize the SQL it uses to read and write the values of columns mapped to simple properties. For example, if your database provides a set of data encryption functions, you can invoke them for individual columns like this:

    @Entity

    class CreditCard {

       @Column(name="credit_card_num")

       @ColumnTransformer(

          read="decrypt(credit_card_num)",

          write="encrypt(?)")

       public String getCreditCardNumber() { return creditCardNumber; }

       public void setCreditCardNumber(String number) { this.creditCardNumber = number; }

       private String creditCardNumber;

    }

or in XML

    <property name="creditCardNumber">

            <column

              name="credit_card_num"

              read="decrypt(credit_card_num)"

              write="encrypt(?)"/>

    </property>

## 注意

You can use the plural form `@ColumnTransformers` if more than one columns need to define either of these rules.

If a property uses more that one column, you must use the `forColumn` attribute to specify which column, the expressions are targeting.

    @Entity

    class User {

       @Type(type="com.acme.type.CreditCardType")

       @Columns( {

          @Column(name="credit_card_num"),

          @Column(name="exp_date") } )

       @ColumnTransformer(

          forColumn="credit_card_num",

          read="decrypt(credit_card_num)",

          write="encrypt(?)")

       public CreditCard getCreditCard() { return creditCard; }

       public void setCreditCard(CreditCard card) { this.creditCard = card; }

       private CreditCard creditCard;

    }

Hibernate applies the custom expressions automatically whenever the property is referenced in a query. This functionality is similar to a derived-property `formula` with two differences:

- The property is backed by one or more columns that are exported as part of automatic schema generation.

- The property is read-write, not read-only.

The `write` expression, if specified, must contain exactly one '?' placeholder for the value.

## 5.7. 補助的なデータベースオブジェクト

Hibernate のスキーマエボリューションツールと連動することで、任意のデータベースオブジェクト（トリガーやストアドプロシージャなど）の CREATE と DROP により、 Hibernate のマッピングファイル内のユーザースキーマをすべて定義することが出来ます。主にトリガやストアドプロシージャのようなデータベースオブジェクトを生成や削除することを意図していますが、実際には `java.sql.Statement.execute()` メソッドによって実行できる任意の SQL コマンド（ALTER、INSERTなど）が実行できます。補助的なデータベースオブジェクトを定義するための、2つの基本的な方法があります。

1つ目の方法は、 CREATE と DROP コマンドをマッピングファイルの外に、明示的に記載することです:

    <hibernate-mapping>

        ...

        <database-object>

            <create>CREATE TRIGGER my_trigger ...</create>

            <drop>DROP TRIGGER my_trigger</drop>

        </database-object>

    </hibernate-mapping>

2つ目の方法は、 CREATE と DROP コマンドの組み立て方を知っているカスタムクラスを提供することです。このカスタムクラスは `org.hibernate.mapping.AuxiliaryDatabaseObject` インタフェースを実装しなければなりません。

    <hibernate-mapping>

        ...

        <database-object>

            <definition class="MyTriggerDefinition"/>

        </database-object>

    </hibernate-mapping>

さらに、あるデータベース方言が使用される時にだけ適用するといったように、データベースオブジェクトが使われるケースを限定できます。

    <hibernate-mapping>

        ...

        <database-object>

            <definition class="MyTriggerDefinition"/>

            <dialect-scope name="org.hibernate.dialect.Oracle9iDialect"/>

            <dialect-scope name="org.hibernate.dialect.Oracle10gDialect"/>

        </database-object>

    </hibernate-mapping>

## 注意

This feature is not supported in Annotations

## 第6章 Types

As an Object/Relational Mapping solution, Hibernate deals with both the Java and JDBC representations of application data. An online catalog application, for example, most likely has `Product` object with a number of attributes such as a `sku`, `name`, etc. For these individual attributes, Hibernate must be able to read the values out of the database and write them back. This 'marshalling' is the function of a Hibernate type, which is an implementation of the `org.hibernate.type.Type` interface. In addition, a Hibernate type describes various aspects of behavior of the Java type such as "how is equality checked?" or "how are values cloned?".

## 重要項目

A Hibernate type is neither a Java type nor a SQL datatype; it provides a information about both.

When you encounter the term type in regards to Hibernate be aware that usage might refer to the Java type, the SQL/JDBC type or the Hibernate type.

Hibernate categorizes types into two high-level groups: value types (see 「Value types」) and entity types (see 「Entity types」).

## 6.1. Value types

The main distinguishing characteristic of a value type is the fact that they do not define their own lifecycle. We say that they are "owned" by something else (specifically an entity, as we will see later) which defines their lifecycle. Value types are further classified into 3 sub-categories: basic types (see 「Basic value types」), composite types (see 「Composite types」) amd collection types (see 「Collection types」).

### 6.1.1. Basic value types

The norm for basic value types is that they map a single database value (column) to a single, non-aggregated Java type. Hibernate provides a number of built-in basic types, which we will present in the following sections by the Java type. Mainly these follow the natural mappings recommended in the JDBC specification. We will later cover how to override these mapping and how to provide and use alternative type mappings.

#### 6.1.1.1. java.lang.String

`org.hibernate.type.StringType`

  Maps a string to the JDBC VARCHAR type. This is the standard mapping for a string if no Hibernate type is specified.

  Registered under `string` and `java.lang.String` in the type registry (see 「Type registry」).

`org.hibernate.type.MaterializedClob`

  Maps a string to a JDBC CLOB type

  Registered under `materialized_clob` in the type registry (see 「Type registry」).

`org.hibernate.type.TextType`

  Maps a string to a JDBC LONGVARCHAR type

  Registered under `text` in the type registry (see 「Type registry」).

#### 6.1.1.2. `java.lang.Character` (or char primitive)

`org.hibernate.type.CharacterType`

  Maps a char or `java.lang.Character` to a JDBC CHAR

  Registered under `char` and `java.lang.Character` in the type registry (see 「Type registry」).

#### 6.1.1.3. `java.lang.Boolean` (or boolean primitive)

`org.hibernate.type.BooleanType`

  Maps a boolean to a JDBC BIT type

  Registered under `boolean` and `java.lang.Boolean` in the type registry (see 「Type registry」).

`org.hibernate.type.NumericBooleanType`

  Maps a boolean to a JDBC INTEGER type as 0 = false, 1 = true

  Registered under `numeric_boolean` in the type registry (see 「Type registry」).

`org.hibernate.type.YesNoType`

  Maps a boolean to a JDBC CHAR type as ('N' | 'n') = false, ( 'Y' | 'y' ) = true

  Registered under `yes_no` in the type registry (see 「Type registry」).

`org.hibernate.type.TrueFalseType`

  Maps a boolean to a JDBC CHAR type as ('F' | 'f') = false, ( 'T' | 't' ) = true

  Registered under `true_false` in the type registry (see 「Type registry」).

#### 6.1.1.4. `java.lang.Byte` (or byte primitive)

`org.hibernate.type.ByteType`

  Maps a byte or `java.lang.Byte` to a JDBC TINYINT

  Registered under `byte` and `java.lang.Byte` in the type registry (see 「Type registry」).

#### 6.1.1.5. `java.lang.Short` (or short primitive)

`org.hibernate.type.ShortType`

  Maps a short or `java.lang.Short` to a JDBC SMALLINT

  Registered under `short` and `java.lang.Short` in the type registry (see 「Type registry」).

#### 6.1.1.6. `java.lang.Integer` (or int primitive)

`org.hibernate.type.IntegerTypes`

  Maps an int or `java.lang.Integer` to a JDBC INTEGER

  Registered under `int` and `java.lang.Integer`in the type registry (see 「Type registry」).

#### 6.1.1.7. `java.lang.Long` (or long primitive)

`org.hibernate.type.LongType`

  Maps a long or `java.lang.Long` to a JDBC BIGINT

  Registered under `long` and `java.lang.Long` in the type registry (see 「Type registry」).

#### 6.1.1.8. `java.lang.Float` (or float primitive)

`org.hibernate.type.FloatType`

  Maps a float or `java.lang.Float` to a JDBC FLOAT

  Registered under `float` and `java.lang.Float` in the type registry (see 「Type registry」).

#### 6.1.1.9. `java.lang.Double` (or double primitive)

`org.hibernate.type.DoubleType`

  Maps a double or `java.lang.Double` to a JDBC DOUBLE

  Registered under `double` and `java.lang.Double` in the type registry (see 「Type registry」).

#### 6.1.1.10. `java.math.BigInteger`

`org.hibernate.type.BigIntegerType`

  Maps a `java.math.BigInteger` to a JDBC NUMERIC

  Registered under `big_integer` and `java.math.BigInteger` in the type registry (see 「Type registry」).

#### 6.1.1.11. `java.math.BigDecimal`

`org.hibernate.type.BigDecimalType`

  Maps a `java.math.BigDecimal` to a JDBC NUMERIC

  Registered under `big_decimal` and `java.math.BigDecimal` in the type registry (see 「Type registry」).

#### 6.1.1.12. `java.util.Date` or `java.sql.Timestamp`

`org.hibernate.type.TimestampType`

  Maps a `java.sql.Timestamp` to a JDBC TIMESTAMP

  Registered under `timestamp`, `java.sql.Timestamp` and `java.util.Date` in the type registry (see 「Type registry」).

#### 6.1.1.13. `java.sql.Time`

`org.hibernate.type.TimeType`

  Maps a `java.sql.Time` to a JDBC TIME

  Registered under `time` and `java.sql.Time` in the type registry (see 「Type registry」).

#### 6.1.1.14. `java.sql.Date`

`org.hibernate.type.DateType`

  Maps a `java.sql.Date` to a JDBC DATE

  Registered under `date` and `java.sql.Date` in the type registry (see 「Type registry」).

#### 6.1.1.15. `java.util.Calendar`

`org.hibernate.type.CalendarType`

  Maps a `java.util.Calendar` to a JDBC TIMESTAMP

  Registered under `calendar`, `java.util.Calendar` and `java.util.GregorianCalendar` in the type registry (see 「Type registry」).

`org.hibernate.type.CalendarDateType`

  Maps a `java.util.Calendar` to a JDBC DATE

  Registered under `calendar_date` in the type registry (see 「Type registry」).

#### 6.1.1.16. `java.util.Currency`

`org.hibernate.type.CurrencyType`

  Maps a `java.util.Currency` to a JDBC VARCHAR (using the Currency code)

  Registered under `currency` and `java.util.Currency` in the type registry (see 「Type registry」).

#### 6.1.1.17. `java.util.Locale`

`org.hibernate.type.LocaleType`

  Maps a `java.util.Locale` to a JDBC VARCHAR (using the Locale code)

  Registered under `locale` and `java.util.Locale` in the type registry (see 「Type registry」).

#### 6.1.1.18. `java.util.TimeZone`

`org.hibernate.type.TimeZoneType`

  Maps a `java.util.TimeZone` to a JDBC VARCHAR (using the TimeZone ID)

  Registered under `timezone` and `java.util.TimeZone` in the type registry (see 「Type registry」).

#### 6.1.1.19. `java.net.URL`

`org.hibernate.type.UrlType`

  Maps a `java.net.URL` to a JDBC VARCHAR (using the external form)

  Registered under `url` and `java.net.URL` in the type registry (see 「Type registry」).

#### 6.1.1.20. `java.lang.Class`

`org.hibernate.type.ClassType`

  Maps a `java.lang.Class` to a JDBC VARCHAR (using the Class name)

  Registered under `class` and `java.lang.Class` in the type registry (see 「Type registry」).

#### 6.1.1.21. `java.sql.Blob`

`org.hibernate.type.BlobType`

  Maps a `java.sql.Blob` to a JDBC BLOB

  Registered under `blob` and `java.sql.Blob` in the type registry (see 「Type registry」).

#### 6.1.1.22. `java.sql.Clob`

`org.hibernate.type.ClobType`

  Maps a `java.sql.Clob` to a JDBC CLOB

  Registered under `clob` and `java.sql.Clob` in the type registry (see 「Type registry」).

#### 6.1.1.23. byte[]

`org.hibernate.type.BinaryType`

  Maps a primitive byte[] to a JDBC VARBINARY

  Registered under `binary` and `byte[]` in the type registry (see 「Type registry」).

`org.hibernate.type.MaterializedBlobType`

  Maps a primitive byte[] to a JDBC BLOB

  Registered under `materialized_blob` in the type registry (see 「Type registry」).

`org.hibernate.type.ImageType`

  Maps a primitive byte[] to a JDBC LONGVARBINARY

  Registered under `image` in the type registry (see 「Type registry」).

#### 6.1.1.24. Byte[]

`org.hibernate.type.BinaryType`

  Maps a java.lang.Byte[] to a JDBC VARBINARY

  Registered under `wrapper-binary`, `Byte[]` and `java.lang.Byte[]` in the type registry (see 「Type registry」).

#### 6.1.1.25. char[]

`org.hibernate.type.CharArrayType`

  Maps a char[] to a JDBC VARCHAR

  Registered under `characters` and `char[]` in the type registry (see 「Type registry」).

#### 6.1.1.26. Character[]

`org.hibernate.type.CharacterArrayType`

  Maps a java.lang.Character[] to a JDBC VARCHAR

  Registered under `wrapper-characters`, `Character[]` and `java.lang.Character[]` in the type registry (see 「Type registry」).

#### 6.1.1.27. `java.util.UUID`

`org.hibernate.type.UUIDBinaryType`

  Maps a java.util.UUID to a JDBC BINARY

  Registered under `uuid-binary` and `java.util.UUID` in the type registry (see 「Type registry」).

`org.hibernate.type.UUIDCharType`

  Maps a java.util.UUID to a JDBC CHAR (though VARCHAR is fine too for existing schemas)

  Registered under `uuid-char` in the type registry (see 「Type registry」).

`org.hibernate.type.PostgresUUIDType`

  Maps a java.util.UUID to the PostgreSQL UUID data type (through `Types#OTHER` which is how the PostgreSQL JDBC driver defines it).

  Registered under `pg-uuid` in the type registry (see 「Type registry」).

#### 6.1.1.28. `java.io.Serializable`

`org.hibernate.type.SerializableType`

  Maps implementors of java.lang.Serializable to a JDBC VARBINARY

  Unlike the other value types, there are multiple instances of this type. It gets registered once under `java.io.Serializable`. Additionally it gets registered under the specific `java.io.Serializable` implementation class names.

### 6.1.2. Composite types

## 注意

The Java Persistence API calls these embedded types, while Hibernate traditionally called them components. Just be aware that both terms are used and mean the same thing in the scope of discussing Hibernate.

Components represent aggregations of values into a single Java type. For example, you might have an Address class that aggregates street, city, state, etc information or a Name class that aggregates the parts of a person's Name. In many ways a component looks exactly like an entity. They are both (generally speaking) classes written specifically for the application. They both might have references to other application-specific classes, as well as to collections and simple JDK types. As discussed before, the only distinguishing factory is the fact that a component does not own its own lifecycle nor does it define an identifier.

### 6.1.3. Collection types

## 重要項目

It is critical understand that we mean the collection itself, not its contents. The contents of the collection can in turn be basic, component or entity types (though not collections), but the collection itself is owned.

Collections are covered in 7章コレクションのマッピング.

## 6.2. Entity types

The definition of entities is covered in detail in 4章永続クラス. For the purpose of this discussion, it is enough to say that entities are (generally application-specific) classes which correlate to rows in a table. Specifically they correlate to the row by means of a unique identifier. Because of this unique identifier, entities exist independently and define their own lifecycle. As an example, when we delete a `Membership`, both the `User` and `Group` entities remain.

## 注意

This notion of entity independence can be modified by the application developer using the concept of cascades. Cascades allow certain operations to continue (or "cascade") across an association from one entity to another. Cascades are covered in detail in 8章関連マッピング.

## 6.3. Significance of type categories

Why do we spend so much time categorizing the various types of types? What is the significance of the distinction?

The main categorization was between entity types and value types. To review we said that entities, by nature of their unique identifier, exist independently of other objects whereas values do not. An application cannot "delete" a Product sku; instead, the sku is removed when the Product itself is deleted (obviously you can update the sku of that Product to null to make it "go away", but even there the access is done through the Product).

Nor can you define an association to that Product sku. You can define an association to Product based on its sku, assuming sku is unique, but that is totally different.

TBC...

## 6.4. Custom types

Hibernate makes it relatively easy for developers to create their own value types. For example, you might want to persist properties of type `java.lang.BigInteger` to `VARCHAR` columns. Custom types are not limited to mapping values to a single table column. So, for example, you might want to concatenate together `FIRST_NAME`, `INITIAL` and `SURNAME` columns into a `java.lang.String`.

There are 3 approaches to developing a custom Hibernate type. As a means of illustrating the different approaches, lets consider a use case where we need to compose a `java.math.BigDecimal` and `java.util.Currency` together into a custom `Money` class.

### 6.4.1. Custom types using `org.hibernate.type.Type`

The first approach is to directly implement the `org.hibernate.type.Type` interface (or one of its derivatives). Probably, you will be more interested in the more specific `org.hibernate.type.BasicType` contract which would allow registration of the type (see 「Type registry」). The benefit of this registration is that whenever the metadata for a particular property does not specify the Hibernate type to use, Hibernate will consult the registry for the exposed property type. In our example, the property type would be `Money`, which is the key we would use to register our type in the registry:

例6.1 Defining and registering the custom Type

    public class MoneyType implements BasicType {

        public String[] getRegistrationKeys() {

            return new String[] { Money.class.getName() };

        }

            public int[] sqlTypes(Mapping mapping) {

                // We will simply use delegation to the standard basic types for BigDecimal and Currency for many of the

                // Type methods...

                return new int[] {

                         BigDecimalType.INSTANCE.sqlType(),

                         CurrencyType.INSTANCE.sqlType(),

                };

                // we could also have honored any registry overrides via...

                //return new int[] {

                //         mappings.getTypeResolver().basic( BigDecimal.class.getName() ).sqlTypes( mappings )[0],

                //         mappings.getTypeResolver().basic( Currency.class.getName() ).sqlTypes( mappings )[0]

                //};

            }

        public Class getReturnedClass() {

            return Money.class;

        }

        public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws SQLException {

            assert names.length == 2;

            BigDecimal amount = BigDecimalType.INSTANCE.get( names[0] ); // already handles null check

            Currency currency = CurrencyType.INSTANCE.get( names[1] ); // already handles null check

            return amount == null && currency == null

                    ? null

                    : new Money( amount, currency );

        }

        public void nullSafeSet(PreparedStatement st, Object value, int index, boolean[] settable, SessionImplementor session)

                throws SQLException {

            if ( value == null ) {

                BigDecimalType.INSTANCE.set( st, null, index );

                CurrencyType.INSTANCE.set( st, null, index+1 );

            }

            else {

                final Money money = (Money) value;

                BigDecimalType.INSTANCE.set( st, money.getAmount(), index );

                CurrencyType.INSTANCE.set( st, money.getCurrency(), index+1 );

            }

        }

        ...

    }

    Configuration cfg = new Configuration();

    cfg.registerTypeOverride( new MoneyType() );

    cfg...;

## 重要項目

It is important that we registered the type before adding mappings.

### 6.4.2. Custom types using `org.hibernate.usertype.UserType`

## 注意

Both `org.hibernate.usertype.UserType` and `org.hibernate.usertype.CompositeUserType` were originally added to isolate user code from internal changes to the `org.hibernate.type.Type` interfaces.

The second approach is the use the `org.hibernate.usertype.UserType` interface, which presents a somewhat simplified view of the `org.hibernate.type.Type` interface. Using a `org.hibernate.usertype.UserType`, our `Money` custom type would look as follows:

例6.2 Defining the custom UserType

    public class MoneyType implements UserType {

        public int[] sqlTypes() {

            return new int[] {

                    BigDecimalType.INSTANCE.sqlType(),

                    CurrencyType.INSTANCE.sqlType(),

            };

        }

        public Class getReturnedClass() {

            return Money.class;

        }

        public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws SQLException {

            assert names.length == 2;

            BigDecimal amount = BigDecimalType.INSTANCE.get( names[0] ); // already handles null check

            Currency currency = CurrencyType.INSTANCE.get( names[1] ); // already handles null check

            return amount == null && currency == null

                    ? null

                    : new Money( amount, currency );

        }

        public void nullSafeSet(PreparedStatement st, Object value, int index) throws SQLException {

            if ( value == null ) {

                BigDecimalType.INSTANCE.set( st, null, index );

                CurrencyType.INSTANCE.set( st, null, index+1 );

            }

            else {

                final Money money = (Money) value;

                BigDecimalType.INSTANCE.set( st, money.getAmount(), index );

                CurrencyType.INSTANCE.set( st, money.getCurrency(), index+1 );

            }

        }

        ...

    }

There is not much difference between the `org.hibernate.type.Type` example and the `org.hibernate.usertype.UserType` example, but that is only because of the snippets shown. If you choose the `org.hibernate.type.Type` approach there are quite a few more methods you would need to implement as compared to the `org.hibernate.usertype.UserType`.

### 6.4.3. Custom types using `org.hibernate.usertype.CompositeUserType`

The third and final approach is the use the `org.hibernate.usertype.CompositeUserType` interface, which differs from `org.hibernate.usertype.UserType` in that it gives us the ability to provide Hibernate the information to handle the composition within the `Money` class (specifically the 2 attributes). This would give us the capability, for example, to reference the `amount` attribute in an HQL query. Using a `org.hibernate.usertype.CompositeUserType`, our `Money` custom type would look as follows:

例6.3 Defining the custom CompositeUserType

    public class MoneyType implements CompositeUserType {

        public String[] getPropertyNames() {

            // ORDER IS IMPORTANT!  it must match the order the columns are defined in the property mapping

            return new String[] { "amount", "currency" };

        }

        public Type[] getPropertyTypes() {

            return new Type[] { BigDecimalType.INSTANCE, CurrencyType.INSTANCE };

        }

        public Class getReturnedClass() {

            return Money.class;

        }

        public Object getPropertyValue(Object component, int propertyIndex) {

            if ( component == null ) {

                return null;

            }

            final Money money = (Money) component;

            switch ( propertyIndex ) {

                case 0: {

                    return money.getAmount();

                }

                case 1: {

                    return money.getCurrency();

                }

                default: {

                    throw new HibernateException( "Invalid property index [" + propertyIndex + "]" );

                }

            }

        }

            public void setPropertyValue(Object component, int propertyIndex, Object value) throws HibernateException {

            if ( component == null ) {

                return;

            }

            final Money money = (Money) component;

            switch ( propertyIndex ) {

                case 0: {

                    money.setAmount( (BigDecimal) value );

                    break;

                }

                case 1: {

                    money.setCurrency( (Currency) value );

                    break;

                }

                default: {

                    throw new HibernateException( "Invalid property index [" + propertyIndex + "]" );

                }

            }

            }

        public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws SQLException {

            assert names.length == 2;

            BigDecimal amount = BigDecimalType.INSTANCE.get( names[0] ); // already handles null check

            Currency currency = CurrencyType.INSTANCE.get( names[1] ); // already handles null check

            return amount == null && currency == null

                    ? null

                    : new Money( amount, currency );

        }

        public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws SQLException {

            if ( value == null ) {

                BigDecimalType.INSTANCE.set( st, null, index );

                CurrencyType.INSTANCE.set( st, null, index+1 );

            }

            else {

                final Money money = (Money) value;

                BigDecimalType.INSTANCE.set( st, money.getAmount(), index );

                CurrencyType.INSTANCE.set( st, money.getCurrency(), index+1 );

            }

        }

        ...

    }

## 6.5. Type registry

Internally Hibernate uses a registry of basic types (see 「Basic value types」) when it needs to resolve the specific `org.hibernate.type.Type` to use in certain situations. It also provides a way for applications to add extra basic type registrations as well as override the standard basic type registrations.

To register a new type or to override an existing type registration, applications would make use of the `registerTypeOverride` method of the `org.hibernate.cfg.Configuration` class when bootstrapping Hibernate. For example, lets say you want Hibernate to use your custom `SuperDuperStringType`; during bootstrap you would call:

例6.4 Overriding the standard `StringType`

    Configuration cfg = ...;

    cfg.registerTypeOverride( new SuperDuperStringType() );

The argument to `registerTypeOverride` is a `org.hibernate.type.BasicType` which is a specialization of the `org.hibernate.type.Type` we saw before. It adds a single method:

例6.5 Snippet from BasicType.java

    /**

             * Get the names under which this type should be registered in the type registry.

             *

             * @return The keys under which to register this type.

             */

            public String[] getRegistrationKeys();

One approach is to use inheritance (`SuperDuperStringType` extends `org.hibernate.type.StringType`); another is to use delegation.

## 第7章 コレクションのマッピング

## 7.1. コレクションの永続化

Naturally Hibernate also allows to persist collections. These persistent collections can contain almost any other Hibernate type, including: basic types, custom types, components and references to other entities. The distinction between value and reference semantics is in this context very important. An object in a collection might be handled with "value" semantics (its life cycle fully depends on the collection owner), or it might be a reference to another entity with its own life cycle. In the latter case, only the "link" between the two objects is considered to be a state held by the collection.

As a requirement persistent collection-valued fields must be declared as an interface type (see 例7.2「Collection mapping using @OneToMany and @JoinColumn」). The actual interface might be `java.util.Set`, `java.util.Collection`, `java.util.List`, `java.util.Map`, `java.util.SortedSet`, `java.util.SortedMap` or anything you like ("anything you like" means you will have to write an implementation of `org.hibernate.usertype.UserCollectionType`).

Notice how in 例7.2「Collection mapping using @OneToMany and @JoinColumn」 the instance variable `parts` was initialized with an instance of `HashSet`. This is the best way to initialize collection valued properties of newly instantiated (non-persistent) instances. When you make the instance persistent, by calling `persist()`, Hibernate will actually replace the `HashSet` with an instance of Hibernate's own implementation of `Set`. Be aware of the following error:

例7.1 Hibernate uses its own collection implementations

    Cat cat = new DomesticCat();

    Cat kitten = new DomesticCat();

    ....

    Set kittens = new HashSet();

    kittens.add(kitten);

    cat.setKittens(kittens);

    session.persist(cat);

    kittens = cat.getKittens(); // Okay, kittens collection is a Set

    (HashSet) cat.getKittens(); // Error!

Hibernate により注入された永続性コレクションは、インターフェース型に応じて、 `HashMap` や `HashSet`、 `TreeMap`、 `TreeSet`、 `ArrayList` のように振舞います。

コレクションインスタンスは、値型として普通に振舞います。永続化オブジェクトに参照されたときに自動的に永続化され、参照がなくなったときに自動的に削除されます。もしある永続化オブジェクトから別の永続化オブジェクトに渡されたら、その要素は現在のテーブルから別のテーブルに移動するかもしれません。２つのエンティティが同じコレクションインスタンスを共有してはいけません。リレーショナルモデルをベースにしているため、コレクション型のプロパティに null 値を代入しても意味がありません。つまり Hibernate は参照先のないコレクションと空のコレクションを区別しません。

## 注意

Use persistent collections the same way you use ordinary Java collections. However, ensure you understand the semantics of bidirectional associations (see 「双方向関連」).

## 7.2. How to map collections

Using annotations you can map `Collection`s, `List`s, `Map`s and `Set`s of associated entities using @OneToMany and @ManyToMany. For collections of a basic or embeddable type use @ElementCollection. In the simplest case a collection mapping looks like this:

例7.2 Collection mapping using @OneToMany and @JoinColumn

    @Entity

    public class Product {

        private String serialNumber;

        private Set<Part> parts = new HashSet<Part>();

        @Id

        public String getSerialNumber() { return serialNumber; }

        void setSerialNumber(String sn) { serialNumber = sn; }

        @OneToMany

        @JoinColumn(name="PART_ID")

        public Set<Part> getParts() { return parts; }

        void setParts(Set parts) { this.parts = parts; }

    }

    @Entity

    public class Part {

       ...

    }

Product describes a unidirectional relationship with Part using the join column PART_ID. In this unidirectional one to many scenario you can also use a join table as seen in 例7.3「Collection mapping using @OneToMany and @JoinTable」.

例7.3 Collection mapping using @OneToMany and @JoinTable

    @Entity

    public class Product {

        private String serialNumber;

        private Set<Part> parts = new HashSet<Part>();

        @Id

        public String getSerialNumber() { return serialNumber; }

        void setSerialNumber(String sn) { serialNumber = sn; }

        @OneToMany

        @JoinTable(

                name="PRODUCT_PARTS",

                joinColumns = @JoinColumn( name="PRODUCT_ID"),

                inverseJoinColumns = @JoinColumn( name="PART_ID")

        )

        public Set<Part> getParts() { return parts; }

        void setParts(Set parts) { this.parts = parts; }

    }

    @Entity

    public class Part {

       ...

    }

Without describing any physical mapping (no `@JoinColumn` or `@JoinTable`), a unidirectional one to many with join table is used. The table name is the concatenation of the owner table name, _, and the other side table name. The foreign key name(s) referencing the owner table is the concatenation of the owner table, _, and the owner primary key column(s) name. The foreign key name(s) referencing the other side is the concatenation of the owner property name, _, and the other side primary key column(s) name. A unique constraint is added to the foreign key referencing the other side table to reflect the one to many.

Lets have a look now how collections are mapped using Hibernate mapping files. In this case the first step is to chose the right mapping element. It depends on the type of interface. For example, a `<set>` element is used for mapping properties of type `Set`.

例7.4 Mapping a Set using <set>

    <class name="Product">

        <id name="serialNumber" column="productSerialNumber"/>

        <set name="parts">

            <key column="productSerialNumber" not-null="true"/>

            <one-to-many class="Part"/>

        </set>

    </class>

In 例7.4「Mapping a Set using <set>」 a one-to-many association links the `Product` and `Part` entities. This association requires the existence of a foreign key column and possibly an index column to the `Part` table. This mapping loses certain semantics of normal Java collections:

- エンティティクラスのインスタンスは、2つ以上のコレクションのインスタンスに属してはいけません。

- コレクションに含まれるエンティティクラスのインスタンスは、コレクションインデックスの値として2度以上現れてはいけません。

Looking closer at the used `<one-to-many>` tag we see that it has the following options.

例7.5 options of <one-to-many> element

    <one-to-many
            class="ClassName"
            not-found="ignore|exception"
            entity-name="EntityName"
            node="element-name"
            embed-xml="true|false"
        />

| `class` （必須）: 関連クラスの名前。
| `not-found` （オプション - デフォルトは `exception`）: 参照先の行がないキャッシュされた識別子をどのように扱うかを指定します: `ignore` を指定すると、行がないことを関連がないものとして扱います。
| `entity-name` （オプション）: `class` の代替である関連クラスのエンティティ名。 `class` の代わりに指定する、関連クラスのエンティティ名。

`<one-to-many>` 要素はカラムを宣言する必要がないことに注意してください。同様に `テーブル` 名を指定する必要もありません。

## 警告

If the foreign key column of a `<one-to-many>` association is declared `NOT NULL`, you must declare the `<key>` mapping `not-null="true"` or use a bidirectional association with the collection mapping marked `inverse="true"`. See 「双方向関連」.

Apart from the `<set>` tag as shown in 例7.4「Mapping a Set using <set>」, there is also `<list>`, `<map>`, `<bag>`, `<array>` and `<primitive-array>` mapping elements. The `<map>` element is representative:

例7.6 Elements of the <map> mapping

    <map
        name="propertyName"
        table="table_name"
        schema="schema_name"
        lazy="true|extra|false"
        inverse="true|false"
        cascade="all|none|save-update|delete|all-delete-orphan|delete-orphan"
        sort="unsorted|natural|comparatorClass"
        order-by="column_name asc|desc"
        where="arbitrary sql where condition"
        fetch="join|select|subselect"
        batch-size="N"
        access="field|property|ClassName"
        optimistic-lock="true|false"
        mutable="true|false"
        node="element-name|."
        embed-xml="true|false"
    >

        <key .... />
        <map-key .... />
        <element .... />
    </map>

| `name` ：コレクション型であるプロパティの名前
| `table` （オプション - デフォルトはプロパティ名）：コレクションテーブルの名前（一対多関連では使用しません）。
| `schema` （オプション）：テーブルスキーマの名前。ルート要素で宣言されているスキーマより優先されます。
| `lazy` （オプション - デフォルトは `true`）： 遅延フェッチを無効にし、関連を常に即時にフェッチにするために使用します。または、「extra-lazy」フェッチを有効にするために使用します。「extra-lazy」フェッチは、ほとんどの操作ではコレクションを初期化しません （非常に大きなコレクションに適しています）。
| `inverse` （オプション - デフォルトは `false`）：このコレクションが双方向関連の「逆」側であるとマークします。
| `cascade` （オプション - デフォルトは `none`）：子エンティティへのカスケード操作を有効にします。
| `sort` （オプション）：コレクションを自然な順序でソートする場合は `natural` を指定します。あるいは Comparator クラスを指定します。
| `order-by` (optional): specifies a table column or columns that define the iteration order of the `Map`, `Set` or bag, together with an optional `asc` or `desc`.
| `where` （オプション）：コレクションの検索や削除の際に使う任意の SQL の`WHERE` 条件を指定します （利用可能なデータの一部分だけをコレクションが含むべきときに、これは有用です）。
| `fetch` （オプション - デフォルトは `select`）：外部結合によるフェッチ、順次選択フェッチ （sequential select fetch） 、順次サブセレクトフェッチ （sequential subselect fetch） のどれかを選択してください。
| `batch-size` （オプション - デフォルトは `1`）：コレクションのインスタンスの遅延フェッチのための「バッチサイズ」を指定します。
| `access` （オプション - デフォルトは `property`）：コレクション型プロパティの値にアクセスするために使用する戦略です。
| `optimistic-lock` （オプション - デフォルトは `true`） コレクションの状態を変えることによって、そのオーナーであるエンティティのバージョンがインクリメントされるかを指定します。 （一対多関連では、ほとんどの場合において無効に設定するのが妥当です。）
| `mutable`（オプション - デフォルトは `true`） `false` 値は、コレクションの要素が変更されないことを表します （ある場合には、少しパフォーマンスを高めます）。

After exploring the basic mapping of collections in the preceding paragraphs we will now focus details like physical mapping considerations, indexed collections and collections of value types.

### 7.2.1. コレクションの外部キー

On the database level collection instances are distinguished by the foreign key of the entity that owns the collection. This foreign key is referred to as the collection key column, or columns, of the collection table. The collection key column is mapped by the `@JoinColumn` annotation respectively the `<key>` XML element.

There can be a nullability constraint on the foreign key column. For most collections, this is implied. For unidirectional one-to-many associations, the foreign key column is nullable by default, so you may need to specify

    @JoinColumn(nullable=false)

or

    <key column="productSerialNumber" not-null="true"/>

The foreign key constraint can use `ON DELETE CASCADE`. In XML this can be expressed via:

    <key column="productSerialNumber" on-delete="cascade"/>

In annotations the Hibernate specific annotation @OnDelete has to be used.

    @OnDelete(action=OnDeleteAction.CASCADE)

See 「Key」 for more information about the `<key>` element.

### 7.2.2. インデックス付きのコレクション

In the following paragraphs we have a closer at the indexed collections `List` and `Map` how the their index can be mapped in Hibernate.

#### 7.2.2.1. Lists

Lists can be mapped in two different ways:

- as ordered lists, where the order is not materialized in the database

- as indexed lists, where the order is materialized in the database

To order lists in memory, add `@javax.persistence.OrderBy` to your property. This annotation takes as parameter a list of comma separated properties (of the target entity) and orders the collection accordingly (eg `firstname asc, age desc`), if the string is empty, the collection will be ordered by the primary key of the target entity.

例7.7 Ordered lists using `@OrderBy`

    @Entity

    public class Customer {

       @Id @GeneratedValue public Integer getId() { return id; }

       public void setId(Integer id) { this.id = id; }

       private Integer id;

       @OneToMany(mappedBy="customer")

       @OrderBy("number")

       public List<Order> getOrders() { return orders; }

       public void setOrders(List<Order> orders) { this.orders = orders; }

       private List<Order> orders;

    }

    @Entity

    public class Order {

       @Id @GeneratedValue public Integer getId() { return id; }

       public void setId(Integer id) { this.id = id; }

       private Integer id;

       public String getNumber() { return number; }

       public void setNumber(String number) { this.number = number; }

       private String number;

       @ManyToOne

       public Customer getCustomer() { return customer; }

       public void setCustomer(Customer customer) { this.customer = customer; }

       private Customer number;

    }

    -- Table schema

    |-------------| |----------|

    | Order       | | Customer |

    |-------------| |----------|

    | id          | | id       |

    | number      | |----------|

    | customer_id |

    |-------------|

To store the index value in a dedicated column, use the `@javax.persistence.OrderColumn` annotation on your property. This annotations describes the column name and attributes of the column keeping the index value. This column is hosted on the table containing the association foreign key. If the column name is not specified, the default is the name of the referencing property, followed by underscore, followed by `ORDER` (in the following example, it would be `orders_ORDER`).

例7.8 Explicit index column using `@OrderColumn`

    @Entity

    public class Customer {

       @Id @GeneratedValue public Integer getId() { return id; }

       public void setId(Integer id) { this.id = id; }

       private Integer id;

       @OneToMany(mappedBy="customer")

       @OrderColumn(name="orders_index")

       public List<Order> getOrders() { return orders; }

       public void setOrders(List<Order> orders) { this.orders = orders; }

       private List<Order> orders;

    }

    @Entity

    public class Order {

       @Id @GeneratedValue public Integer getId() { return id; }

       public void setId(Integer id) { this.id = id; }

       private Integer id;

       public String getNumber() { return number; }

       public void setNumber(String number) { this.number = number; }

       private String number;

       @ManyToOne

       public Customer getCustomer() { return customer; }

       public void setCustomer(Customer customer) { this.customer = customer; }

       private Customer number;

    }

    -- Table schema

    |--------------| |----------|

    | Order        | | Customer |

    |--------------| |----------|

    | id           | | id       |

    | number       | |----------|

    | customer_id  |

    | orders_order |

    |--------------|

## 注意

We recommend you to convert `the legacy @org.hibernate.annotations.IndexColumn` usages to `@OrderColumn` unless you are making use of the base property. The `base` property lets you define the index value of the first element (aka as base index). The usual value is `0` or `1`. The default is 0 like in Java.

Looking again at the Hibernate mapping file equivalent, the index of an array or list is always of type `integer` and is mapped using the `<list-index>` element. The mapped column contains sequential integers that are numbered from zero by default.

例7.9 index-list element for indexed collections in xml mapping

    <list-index
            column="column_name"
            base="0|1|..."/>

| `column_name` (required): the name of the column holding the collection index values.
| `base` (optional - defaults to `0`): the value of the index column that corresponds to the first element of the list or array.

If your table does not have an index column, and you still wish to use `List` as the property type, you can map the property as a Hibernate <bag>. A bag does not retain its order when it is retrieved from the database, but it can be optionally sorted or ordered.

#### 7.2.2.2. Maps

The question with `Map`s is where the key value is stored. There are everal options. Maps can borrow their keys from one of the associated entity properties or have dedicated columns to store an explicit key.

To use one of the target entity property as a key of the map, use `@MapKey(name="myProperty")`, where `myProperty` is a property name in the target entity. When using `@MapKey` without the name attribuate, the target entity primary key is used. The map key uses the same column as the property pointed out. There is no additional column defined to hold the map key, because the map key represent a target property. Be aware that once loaded, the key is no longer kept in sync with the property. In other words, if you change the property value, the key will not change automatically in your Java model.

例7.10 Use of target entity property as map key via `@MapKey`

    @Entity

    public class Customer {

       @Id @GeneratedValue public Integer getId() { return id; }

       public void setId(Integer id) { this.id = id; }

       private Integer id;

       @OneToMany(mappedBy="customer")

       @MapKey(name="number")

       public Map<String,Order> getOrders() { return orders; }

       public void setOrders(Map<String,Order> order) { this.orders = orders; }

       private Map<String,Order> orders;

    }

    @Entity

    public class Order {

       @Id @GeneratedValue public Integer getId() { return id; }

       public void setId(Integer id) { this.id = id; }

       private Integer id;

       public String getNumber() { return number; }

       public void setNumber(String number) { this.number = number; }

       private String number;

       @ManyToOne

       public Customer getCustomer() { return customer; }

       public void setCustomer(Customer customer) { this.customer = customer; }

       private Customer number;

    }

    -- Table schema

    |-------------| |----------|

    | Order       | | Customer |

    |-------------| |----------|

    | id          | | id       |

    | number      | |----------|

    | customer_id |

    |-------------|

Alternatively the map key is mapped to a dedicated column or columns. In order to customize the mapping use one of the following annotations:

- @`MapKeyColumn` if the map key is a basic type. If you don't specify the column name, the name of the property followed by underscore followed by `KEY` is used (for example `orders_KEY`).

- `@MapKeyEnumerated` / `@MapKeyTemporal` if the map key type is respectively an enum or a `Date`.

- `@MapKeyJoinColumn`/`@MapKeyJoinColumns` if the map key type is another entity.

- `@AttributeOverride`/`@AttributeOverrides` when the map key is a embeddable object. Use `key.` as a prefix for your embeddable object property names.

You can also use `@MapKeyClass` to define the type of the key if you don't use generics.

例7.11 Map key as basic type using `@MapKeyColumn`

    @Entity

    public class Customer {

       @Id @GeneratedValue public Integer getId() { return id; }

       public void setId(Integer id) { this.id = id; }

       private Integer id;

       @OneToMany @JoinTable(name="Cust_Order")

       @MapKeyColumn(name="orders_number")

       public Map<String,Order> getOrders() { return orders; }

       public void setOrders(Map<String,Order> orders) { this.orders = orders; }

       private Map<String,Order> orders;

    }

    @Entity

    public class Order {

       @Id @GeneratedValue public Integer getId() { return id; }

       public void setId(Integer id) { this.id = id; }

       private Integer id;

       public String getNumber() { return number; }

       public void setNumber(String number) { this.number = number; }

       private String number;

       @ManyToOne

       public Customer getCustomer() { return customer; }

       public void setCustomer(Customer customer) { this.customer = customer; }

       private Customer number;

    }

    -- Table schema

    |-------------| |----------| |---------------|

    | Order       | | Customer | | Cust_Order    |

    |-------------| |----------| |---------------|

    | id          | | id       | | customer_id   |

    | number      | |----------| | order_id      |

    | customer_id |              | orders_number |

    |-------------|              |---------------|

## 注意

We recommend you to migrate from `@org.hibernate.annotations.MapKey` / `@org.hibernate.annotation.MapKeyManyToMany` to the new standard approach described above

Using Hibernate mapping files there exists equivalent concepts to the descibed annotations. You have to use `<map-key>`, `<map-key-many-to-many>` and `<composite-map-key>`. `<map-key>` is used for any basic type, `<map-key-many-to-many>` for an entity reference and `<composite-map-key>` for a composite type.

例7.12 map-key xml mapping element

    <map-key
            column="column_name"
            formula="any SQL expression"
            type="type_name"
            node="@attribute-name"
            length="N"/>

| `column` (optional): the name of the column holding the collection index values.
| `formula` (optional): a SQL formula used to evaluate the key of the map.
| `type` (required): the type of the map keys.

例7.13 map-key-many-to-many

    <map-key-many-to-many
            column="column_name"
            formula="any SQL expression"
            class="ClassName"
    />

| `column` (optional): the name of the foreign key column for the collection index values.
| `formula` (optional): a SQ formula used to evaluate the foreign key of the map key.
| `class` (required): the entity class used as the map key.

### 7.2.3. Collections of basic types and embeddable objects

In some situations you don't need to associate two entities but simply create a collection of basic types or embeddable objects. Use the `@ElementCollection` for this case.

例7.14 Collection of basic types mapped via `@ElementCollection`

    @Entity

    public class User {

       [...]

       public String getLastname() { ...}

       @ElementCollection

       @CollectionTable(name="Nicknames", joinColumns=@JoinColumn(name="user_id"))

       @Column(name="nickname")

       public Set<String> getNicknames() { ... }

    }

The collection table holding the collection data is set using the `@CollectionTable` annotation. If omitted the collection table name defaults to the concatenation of the name of the containing entity and the name of the collection attribute, separated by an underscore. In our example, it would be `User_nicknames`.

The column holding the basic type is set using the `@Column` annotation. If omitted, the column name defaults to the property name: in our example, it would be `nicknames`.

But you are not limited to basic types, the collection type can be any embeddable object. To override the columns of the embeddable object in the collection table, use the `@AttributeOverride` annotation.

例7.15 @ElementCollection for embeddable objects

    @Entity

    public class User {

       [...]

       public String getLastname() { ...}

       @ElementCollection

       @CollectionTable(name="Addresses", joinColumns=@JoinColumn(name="user_id"))

       @AttributeOverrides({

          @AttributeOverride(name="street1", column=@Column(name="fld_street"))

       })

       public Set<Address> getAddresses() { ... }

    }

    @Embeddable

    public class Address {

       public String getStreet1() {...}

       [...]

    }

Such an embeddable object cannot contains a collection itself.

## 注意

in `@AttributeOverride`, you must use the `value.` prefix to override properties of the embeddable object used in the map value and the `key.` prefix to override properties of the embeddable object used in the map key.

    @Entity

    public class User {

       @ElementCollection

       @AttributeOverrides({

          @AttributeOverride(name="key.street1", column=@Column(name="fld_street")),

          @AttributeOverride(name="value.stars", column=@Column(name="fld_note"))

       })

       public Map<Address,Rating> getFavHomes() { ... }

## 注意

We recommend you to migrate from `@org.hibernate.annotations.CollectionOfElements` to the new `@ElementCollection` annotation.

Using the mapping file approach a collection of values is mapped using the `<element>` tag. For example:

例7.16 <element> tag for collection values using mapping files

    <element
            column="column_name"
            formula="any SQL expression"
            type="typename"
            length="L"
            precision="P"
            scale="S"
            not-null="true|false"
            unique="true|false"
            node="element-name"
    />

| `column` (optional): the name of the column holding the collection element values.
| `formula` (optional): an SQL formula used to evaluate the element.
| `type` (required): the type of the collection element.

## 7.3. 高度なコレクションマッピング

### 7.3.1. ソートされたコレクション

Hibernate supports collections implementing `java.util.SortedMap` and `java.util.SortedSet`. With annotations you declare a sort comparator using `@Sort`. You chose between the comparator types unsorted, natural or custom. If you want to use your own comparator implementation, you'll also have to specify the implementation class using the `comparator` attribute. Note that you need to use either a `SortedSet` or a `SortedMap` interface.

例7.17 Sorted collection with @Sort

    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)

    @JoinColumn(name="CUST_ID")

    @Sort(type = SortType.COMPARATOR, comparator = TicketComparator.class)

    public SortedSet<Ticket> getTickets() {

        return tickets;

    }

Using Hibernate mapping files you specify a comparator in the mapping file with `<sort>`:

例7.18 Sorted collection using xml mapping

    <set name="aliases"

                table="person_aliases"

                sort="natural">

        <key column="person"/>

        <element column="name" type="string"/>

    </set>

    <map name="holidays" sort="my.custom.HolidayComparator">

        <key column="year_id"/>

        <map-key column="hol_name" type="string"/>

        <element column="hol_date" type="date"/>

    </map>

`sort` 属性に設定できる値は `unsorted` と `natural` および、 `java.util.Comparator` を実装したクラスの名前です。

## ティップ

ソートされたコレクションは実質的には `java.util.TreeSet` や `java.util.TreeMap` のように振舞います。

If you want the database itself to order the collection elements, use the `order-by` attribute of `set`, `bag` or `map` mappings. This solution is implemented using `LinkedHashSet` or `LinkedHashMap` and performs the ordering in the SQL query and not in the memory.

例7.19 Sorting in database using order-by

    <set name="aliases" table="person_aliases" order-by="lower(name) asc">

        <key column="person"/>

        <element column="name" type="string"/>

    </set>

    <map name="holidays" order-by="hol_date, hol_name">

        <key column="year_id"/>

        <map-key column="hol_name" type="string"/>

        <element column="hol_date type="date"/>

    </map>

## 注記

The value of the `order-by` attribute is an SQL ordering, not an HQL ordering.

関連は、コレクションの `filter()` を使うことで、実行時に任意の criteria によってソートすることも可能です。

例7.20 Sorting via a query filter

    sortedUsers = s.createFilter( group.getUsers(), "order by this.name" ).list();

### 7.3.2. 双方向関連

双方向関連 は関連のどちら「側」からでもナビゲーションできます。2種類の双方向関連がサポートされています：

one-to-many

  片側が set か bag 、もう片方が単一値です。

many-to-many

  両側が set か bag です。

Often there exists a many to one association which is the owner side of a bidirectional relationship. The corresponding one to many association is in this case annotated by `@OneToMany(mappedBy=...)`

例7.21 Bidirectional one to many with many to one side as association owner

    @Entity

    public class Troop {

        @OneToMany(mappedBy="troop")

        public Set<Soldier> getSoldiers() {

        ...

    }

    @Entity

    public class Soldier {

        @ManyToOne

        @JoinColumn(name="troop_fk")

        public Troop getTroop() {

        ...

    }

`Troop` has a bidirectional one to many relationship with `Soldier` through the `troop` property. You don't have to (must not) define any physical mapping in the `mappedBy` side.

To map a bidirectional one to many, with the one-to-many side as the owning side, you have to remove the `mappedBy` element and set the many to one `@JoinColumn` as insertable and updatable to false. This solution is not optimized and will produce additional UPDATE statements.

例7.22 Bidirectional associtaion with one to many side as owner

    @Entity

    public class Troop {

        @OneToMany

        @JoinColumn(name="troop_fk") //we need to duplicate the physical information

        public Set<Soldier> getSoldiers() {

        ...

    }

    @Entity

    public class Soldier {

        @ManyToOne

        @JoinColumn(name="troop_fk", insertable=false, updatable=false)

        public Troop getTroop() {

        ...

    }

How does the mappping of a bidirectional mapping look like in Hibernate mapping xml? There you define a bidirectional one-to-many association by mapping a one-to-many association to the same table column(s) as a many-to-one association and declaring the many-valued end `inverse="true"`.

例7.23 Bidirectional one to many via Hibernate mapping files

    <class name="Parent">

        <id name="id" column="parent_id"/>

        ....

        <set name="children" inverse="true">

            <key column="parent_id"/>

            <one-to-many class="Child"/>

        </set>

    </class>

    <class name="Child">

        <id name="id" column="child_id"/>

        ....

        <many-to-one name="parent"

            class="Parent"

            column="parent_id"

            not-null="true"/>

    </class>

関連の片側に `inverse="true"` を設定しても、カスケード操作に影響を与えません。これらは直交した概念です。

A many-to-many association is defined logically using the `@ManyToMany` annotation. You also have to describe the association table and the join conditions using the `@JoinTable` annotation. If the association is bidirectional, one side has to be the owner and one side has to be the inverse end (ie. it will be ignored when updating the relationship values in the association table):

例7.24 Many to many association via @ManyToMany

    @Entity

    public class Employer implements Serializable {

        @ManyToMany(

            targetEntity=org.hibernate.test.metadata.manytomany.Employee.class,

            cascade={CascadeType.PERSIST, CascadeType.MERGE}

        )

        @JoinTable(

            name="EMPLOYER_EMPLOYEE",

            joinColumns=@JoinColumn(name="EMPER_ID"),

            inverseJoinColumns=@JoinColumn(name="EMPEE_ID")

        )

        public Collection getEmployees() {

            return employees;

        }

        ...

    }

    @Entity

    public class Employee implements Serializable {

        @ManyToMany(

            cascade = {CascadeType.PERSIST, CascadeType.MERGE},

            mappedBy = "employees",

            targetEntity = Employer.class

        )

        public Collection getEmployers() {

            return employers;

        }

    }

In this example `@JoinTable` defines a `name`, an array of join columns, and an array of inverse join columns. The latter ones are the columns of the association table which refer to the `Employee` primary key (the "other side"). As seen previously, the other side don't have to (must not) describe the physical mapping: a simple `mappedBy` argument containing the owner side property name bind the two.

As any other annotations, most values are guessed in a many to many relationship. Without describing any physical mapping in a unidirectional many to many the following rules applied. The table name is the concatenation of the owner table name, _ and the other side table name. The foreign key name(s) referencing the owner table is the concatenation of the owner table name, _ and the owner primary key column(s). The foreign key name(s) referencing the other side is the concatenation of the owner property name, _, and the other side primary key column(s). These are the same rules used for a unidirectional one to many relationship.

例7.25 Default values for `@ManyToMany` (uni-directional)

    @Entity

    public class Store {

        @ManyToMany(cascade = CascadeType.PERSIST)

        public Set<City> getImplantedIn() {

            ...

        }

    }

    @Entity

    public class City {

        ... //no bidirectional relationship

    }

A `Store_City` is used as the join table. The `Store_id` column is a foreign key to the `Store` table. The `implantedIn_id` column is a foreign key to the `City` table.

Without describing any physical mapping in a bidirectional many to many the following rules applied. The table name is the concatenation of the owner table name, _ and the other side table name. The foreign key name(s) referencing the owner table is the concatenation of the other side property name, _, and the owner primary key column(s). The foreign key name(s) referencing the other side is the concatenation of the owner property name, _, and the other side primary key column(s). These are the same rules used for a unidirectional one to many relationship.

例7.26 Default values for `@ManyToMany` (bi-directional)

    @Entity

    public class Store {

        @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})

        public Set<Customer> getCustomers() {

            ...

        }

    }

    @Entity

    public class Customer {

        @ManyToMany(mappedBy="customers")

        public Set<Store> getStores() {

            ...

        }

    }

A `Store_Customer` is used as the join table. The `stores_id` column is a foreign key to the `Store` table. The `customers_id` column is a foreign key to the `Customer` table.

Using Hibernate mapping files you can map a bidirectional many-to-many association by mapping two many-to-many associations to the same database table and declaring one end as inverse.

## 注意

You cannot select an indexed collection.

例7.27「Many to many association using Hibernate mapping files」 shows a bidirectional many-to-many association that illustrates how each category can have many items and each item can be in many categories:

例7.27 Many to many association using Hibernate mapping files

    <class name="Category">

        <id name="id" column="CATEGORY_ID"/>

        ...

        <bag name="items" table="CATEGORY_ITEM">

            <key column="CATEGORY_ID"/>

            <many-to-many class="Item" column="ITEM_ID"/>

        </bag>

    </class>

    <class name="Item">

        <id name="id" column="ITEM_ID"/>

        ...

        <!-- inverse end -->

        <bag name="categories" table="CATEGORY_ITEM" inverse="true">

            <key column="ITEM_ID"/>

            <many-to-many class="Category" column="CATEGORY_ID"/>

        </bag>

    </class>

関連の inverse 側にのみ行われた変更は永続化 されません。これは、 Hibernate は全ての双方向関連について、メモリ上に２つの表現を持っているという意味です。つまり一つは A から B へのリンクで、もう一つは B から A へのリンクということです。 Java のオブジェクトモデルについて考え、 Java で双方向関係をどうやって作るかを考えれば、これは理解しやすいです。下記に、 Java での双方向関連を示します。

例7.28 Effect of inverse vs. non-inverse side of many to many associations

    category.getItems().add(item);           // The category now "knows" about the relationship

    item.getCategories().add(category);      // The item now "knows" about the relationship

    session.persist(item);                   // The relationship won't be saved!

    session.persist(category);               // The relationship will be saved

関連の inverse ではない側は、メモリ上の表現をデータベースに保存するのに使われます。

### 7.3.3. インデックス付きコレクションと双方向関連

There are some additional considerations for bidirectional mappings with indexed collections (where one end is represented as a `<list>` or `<map>`) when using Hibernate mapping files. If there is a property of the child class that maps to the index column you can use `inverse="true"` on the collection mapping:

例7.29 Bidirectional association with indexed collection

    <class name="Parent">

        <id name="id" column="parent_id"/>

        ....

        <map name="children" inverse="true">

            <key column="parent_id"/>

            <map-key column="name"

                type="string"/>

            <one-to-many class="Child"/>

        </map>

    </class>

    <class name="Child">

        <id name="id" column="child_id"/>

        ....

        <property name="name"

            not-null="true"/>

        <many-to-one name="parent"

            class="Parent"

            column="parent_id"

            not-null="true"/>

    </class>

しかし、子クラスにそのようなプロパティがない場合は、関連を真に双方向であると考えることができません （関連の片側に利用できる情報がありますが、もう一方にはありません）。この場合は、コレクションに `inverse="true"` をマッピングできません。代わりに、次のようなマッピングが使えます：

例7.30 Bidirectional association with indexed collection, but no index column

    <class name="Parent">

        <id name="id" column="parent_id"/>

        ....

        <map name="children">

            <key column="parent_id"

                not-null="true"/>

            <map-key column="name"

                type="string"/>

            <one-to-many class="Child"/>

        </map>

    </class>

    <class name="Child">

        <id name="id" column="child_id"/>

        ....

        <many-to-one name="parent"

            class="Parent"

            column="parent_id"

            insert="false"

            update="false"

            not-null="true"/>

    </class>

Note that in this mapping, the collection-valued end of the association is responsible for updates to the foreign key.

### 7.3.4. 3項関連

3項関連のマッピングには3つのアプローチがあります。1つ目は関連をインデックスとして `Map` を使用するアプローチです：

例7.31 Ternary association mapping

    @Entity

    public class Company {

       @Id

       int id;

       ...

       @OneToMany // unidirectional

       @MapKeyJoinColumn(name="employee_id")

       Map<Employee, Contract> contracts;

    }

    // or

    <map name="contracts">

        <key column="employer_id" not-null="true"/>

        <map-key-many-to-many column="employee_id" class="Employee"/>

        <one-to-many class="Contract"/>

    </map>

A second approach is to remodel the association as an entity class. This is the most common approach. A final alternative is to use composite elements, which will be discussed later.

### 7.3.5. `Using an <idbag>`

The majority of the many-to-many associations and collections of values shown previously all map to tables with composite keys, even though it has been suggested that entities should have synthetic identifiers (surrogate keys). A pure association table does not seem to benefit much from a surrogate key, although a collection of composite values might. For this reason Hibernate provides a feature that allows you to map many-to-many associations and collections of values to a table with a surrogate key.

bag のセマンティックスを持った `List`（または `Collection`）を `<idbag>` 要素にマッピングできます。

    <idbag name="lovers" table="LOVERS">

        <collection-id column="ID" type="long">

            <generator class="sequence"/>

        </collection-id>

        <key column="PERSON1"/>

        <many-to-many column="PERSON2" class="Person" fetch="join"/>

    </idbag>

ご存知のように `<idbag>` はエンティティクラスのように人工的な id ジェネレータを持っています。異なる代理キーをそれぞれのコレクションの列に割り当てます。しかし、 Hibernate はある行の代理キーの値を見つけ出す機構を持っていません。

`<idbag>` を更新するパフォーマンスは通常の `<bag>` よりも良いことに注目してください。 Hibernate は個々の行を効果的に見つけることができ、 list や map 、 set のように個別にその行を更新、削除できます。

現在の実装では、 `native` という id 生成戦略を `<idbag>` コレクションの識別子に対して使えません。

## 7.4. コレクションの例

This section covers collection examples.

The following class has a collection of `Child` instances:

例7.32 Example classes `Parent` and `Child`

    public class Parent {

        private long id;

        private Set<Child> children;

        // getter/setter

        ...

    }

    public class Child {

       private long id;

       private String name

       // getter/setter

       ...

    }

If each child has, at most, one parent, the most natural mapping is a one-to-many association:

例7.33 One to many unidirectional `Parent-Child` relationship using annotations

    public class Parent {

        @Id

        @GeneratedValue

        private long id;

        @OneToMany

        private Set<Child> children;

        // getter/setter

        ...

    }

    public class Child {

       @Id

       @GeneratedValue

       private long id;

       private String name;

       // getter/setter

       ...

    }

例7.34 One to many unidirectional `Parent-Child` relationship using mapping files

    <hibernate-mapping>

        <class name="Parent">

            <id name="id">

                <generator class="sequence"/>

            </id>

            <set name="children">

                <key column="parent_id"/>

                <one-to-many class="Child"/>

            </set>

        </class>

        <class name="Child">

            <id name="id">

                <generator class="sequence"/>

            </id>

            <property name="name"/>

        </class>

    </hibernate-mapping>

これは以下のテーブル定義にマッピングします。

例7.35 Table definitions for unidirectional `Parent`-`Child` relationship

    create table parent ( id bigint not null primary key )

    create table child ( id bigint not null primary key, name varchar(255), parent_id bigint )

    alter table child add constraint childfk0 (parent_id) references parent

もし parent が 要求 されるなら、双方向の一対多関連を使用してください：

例7.36 One to many bidirectional `Parent-Child` relationship using annotations

    public class Parent {

        @Id

        @GeneratedValue

        private long id;

        @OneToMany(mappedBy="parent")

        private Set<Child> children;

        // getter/setter

        ...

    }

    public class Child {

       @Id

       @GeneratedValue

       private long id;

       private String name;

       @ManyToOne

       private Parent parent;

       // getter/setter

       ...

    }

例7.37 One to many bidirectional `Parent-Child` relationship using mapping files

    <hibernate-mapping>

        <class name="Parent">

            <id name="id">

                <generator class="sequence"/>

            </id>

            <set name="children" inverse="true">

                <key column="parent_id"/>

                <one-to-many class="Child"/>

            </set>

        </class>

        <class name="Child">

            <id name="id">

                <generator class="sequence"/>

            </id>

            <property name="name"/>

            <many-to-one name="parent" class="Parent" column="parent_id" not-null="true"/>

        </class>

    </hibernate-mapping>

`NOT NULL` 制約に注意してください。

例7.38 Table definitions for bidirectional `Parent`-`Child` relationship

    create table parent ( id bigint not null primary key )

    create table child ( id bigint not null

                         primary key,

                         name varchar(255),

                         parent_id bigint not null )

    alter table child add constraint childfk0 (parent_id) references parent

Alternatively, if this association must be unidirectional you can enforce the `NOT NULL` constraint.

例7.39 Enforcing NOT NULL constraint in unidirectional relation using annotations

    public class Parent {

        @Id

        @GeneratedValue

        private long id;

        @OneToMany(optional=false)

        private Set<Child> children;

        // getter/setter

        ...

    }

    public class Child {

       @Id

       @GeneratedValue

       private long id;

       private String name;

       // getter/setter

       ...

    }

例7.40 Enforcing NOT NULL constraint in unidirectional relation using mapping files

    <hibernate-mapping>

        <class name="Parent">

            <id name="id">

                <generator class="sequence"/>

            </id>

            <set name="children">

                <key column="parent_id" not-null="true"/>

                <one-to-many class="Child"/>

            </set>

        </class>

        <class name="Child">

            <id name="id">

                <generator class="sequence"/>

            </id>

            <property name="name"/>

        </class>

    </hibernate-mapping>

On the other hand, if a child has multiple parents, a many-to-many association is appropriate.

例7.41 Many to many `Parent-Child` relationship using annotations

    public class Parent {

        @Id

        @GeneratedValue

        private long id;

        @ManyToMany

        private Set<Child> children;

        // getter/setter

        ...

    }

    public class Child {

       @Id

       @GeneratedValue

       private long id;

       private String name;

       // getter/setter

       ...

    }

例7.42 Many to many `Parent-Child` relationship using mapping files

    <hibernate-mapping>

        <class name="Parent">

            <id name="id">

                <generator class="sequence"/>

            </id>

            <set name="children" table="childset">

                <key column="parent_id"/>

                <many-to-many class="Child" column="child_id"/>

            </set>

        </class>

        <class name="Child">

            <id name="id">

                <generator class="sequence"/>

            </id>

            <property name="name"/>

        </class>

    </hibernate-mapping>

テーブル定義は以下のようになります:

例7.43 Table definitions for many to many releationship

    create table parent ( id bigint not null primary key )
    create table child ( id bigint not null primary key, name varchar(255) )
    create table childset ( parent_id bigint not null,
                            child_id bigint not null,
                            primary key ( parent_id, child_id ) )
    alter table childset add constraint childsetfk0 (parent_id) references parent
    alter table childset add constraint childsetfk1 (child_id) references child

For more examples and a complete explanation of a parent/child relationship mapping, see 24章例： 親/子供 for more information. Even more complex association mappings are covered in the next chapter.

## 第8章 関連マッピング

## 8.1. イントロダクション

関連マッピングはしばしば理解が最も難しいものになります。この章では、基本的な一つ一つのケースについて述べます。単方向のマッピングから始め、それから双方向のケースについて考えていきます。例として、 `Person` と `Address` を用います。

関連は、結合テーブルを入れるかかどうかと、多重度によって分類することにします。

null 可能な外部キーは従来型データモデリングの中では良い習慣と見なされていないため、すべての例で not null の外部キーを使用します。これは Hibernate の要件ではありません。 not null 制約を外したとしても、マッピングは問題なく動作します。

## 8.2. 単方向関連

### 8.2.1. Many-to-one

単方向多対一関連 は単方向関連の中で最も一般的なものです。

    <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 )

### 8.2.2. One-to-one

外部キーの単方向一対一関連 はほとんど同じものです。唯一違うのは、カラムのユニークな制約です。

    <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 )

主キーの単方向一対一関連 は通常、特別な 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 )

### 8.2.3. One-to-many

外部キーの単方向一対多関連 はとても特殊なケースで、あまり推奨されていません。

    <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 )

このような関連のために結合テーブルを使うことをお薦めします。

## 8.3. 結合テーブルを使った単方向関連

### 8.3.1. 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 )

### 8.3.2. Many-to-one

結合テーブルの単方向多対一関連 は関連が任意であるときに非常に一般的なものです。

    <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 )

### 8.3.3. One-to-one

結合テーブルの単方向一対一関連 は、非常に特殊ですが不可能ではありません。

    <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 )

### 8.3.4. Many-to-many

最後に、 単方向多対多関連 を示します。

    <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 )

## 8.4. 双方向関連

### 8.4.1. 一対多/多対一

双方向多対一関連 は最も一般的な関連です。 （標準的な親子関係です）

    <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 )

`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

    >

If the underlying foreign key column is `NOT NULL`, it is important that you define `not-null="true"` on the `<key>` element of the collection mapping. Do not only declare `not-null="true"` on a possible nested `<column>` element, but on the `<key>` element.

### 8.4.2. One-to-one

外部キーの双方向一対一関連 は非常に一般的です。

    <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 )

主キーの双方向一対一関連 は特殊な 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 )

## 8.5. 結合テーブルを使った双方向関連

### 8.5.1. 一対多/多対一

結合テーブルの双方向一対多関連 です。 `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 )

### 8.5.2. 一対一

結合テーブルの双方向一対一関連 は非常に特殊ですが、可能です。

    <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 )

### 8.5.3. Many-to-many

最後に、 双方向多対多関連 を示します。

    <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 )

## 8.6. より複雑な関連マッピング

より複雑な関連結合は 極めて 稀です。マッピングドキュメントに 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"/>

そして、関連を 現時点の インスタンス （`effectiveEndDate` が null であるもの）にマッピングします。以下のようになります：

    <many-to-one name="currentAccountInfo"

            property-ref="currentAccountKey"

            class="AccountInfo">

        <column name="accountNumber"/>

        <formula

    >'1'</formula>

    </many-to-one

    >

さらに複雑な例では、 `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

    >

この機能は非常に強力です。しかしこのような場合、普通は HQL や criteria クエリを使う方がより実践的です。

## 第9章 コンポーネントのマッピング

コンポーネント の概念は、 Hibernate を通して様々な状況の中で異なる目的のために再利用されます。

## 9.1. 依存オブジェクト

コンポーネントは、エンティティの参照ではなく値型として永続化された、包含されたオブジェクトです。「コンポーネント」という言葉については、コンポジションというオブジェクト指向の概念を参照してください（アーキテクチャレベルのコンポーネントではありません）。例えば、以下の 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;

        }

    }

いま、 `Name` は `Person` のコンポーネントとして永続化することが出来ます。ここで `Name` は永続化属性に対して getter 、 setter メソッドを定義しますが、インターフェースや識別子プロパティを定義する必要がないことに注意して下さい。

マッピング定義は以下のようになります。

    <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

    >

Person テーブルは `pid`、 `birthday`、 `initial`、 `first`、 `last` カラムを持ちます。

全ての値型のように、コンポーネントは参照の共有をすることができません。言い換えると、二人の Person は同じ名前を持つことができますが、二つの Person オブジェクトは「値が同じだけ」の別々の name オブジェクトを含んでいるということです。コンポーネントの null 値のセマンティクスは アドホック です。コンポーネントのオブジェクトを再読み込みする際、 Hibernate はコンポーネントのすべてのカラムが null であるならコンポーネント自体が null であると考えます。これは大抵の場合問題ありません。

コンポーネントの属性はどんな Hibernate の型でも構いません（コレクション、 many-to-one 関連、他のコンポーネントなど）。ネストされたコンポーネントは滅多に使わないと考えるべきでは ありません 。 Hibernate は非常にきめの細かいオブジェクトモデルをサポートするように意図されています。

`<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

    >

## 9.2. 従属するオブジェクトのコレクション

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

    >

## 重要項目

注記: コンポジットエレメントの `Set` を定義したなら、 `equals()` と `hashCode()` を正しく実装することが重要です。

コンポジットエレメントはコレクションを含まず、コンポーネントを含むこともあります。コンポジットエレメント自身がコンポーネントを含んでいる場合は `<nested-composite-element>` を使用してください。コンポーネントのコレクション自身がコンポーネントを持つというケースはめったにありません。この段階までに、 one-to-many 関連の方がより適切でないかと熟考してください。コンポジットエレメントをエンティティとして再度モデリングしてみてください。しかしこれは Java のモデルとしては同じですが、リレーショナルモデルと永続動作はまだ若干異なることに注意してください。

もし `<set>` を使用するのであれば、コンポジットエレメントのマッピングが null 値が可能な属性をサポートしていないことに注意してください。 Hibernate はオブジェクトを削除するとき、レコードを識別するためにそれぞれのカラムの値を使用する必要があるため、 null 値を持つことが出来ません （コンポジットエレメントテーブルには別の主キーカラムはありません）。 コンポジットエレメントに not-null の属性のみを使用するか、または `<list>`、`<map>`、 `<bag>`、`<idbag>` を選択する必要があります。

コンポジットエレメントの特別なケースとして、ネストされた `<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

    >

もちろん、双方向関連のナビゲーションのために反対側から purchase への参照を作ることは出来ません。コンポーネントは値型であり、参照を共有できないことを覚えておいてください。一つの `Purchase` は一つの `Order` の set に存在できますが、同時に `Item` から参照することは出来ません。

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

    >

コンポジットエレメントは他のエンティティへの関連として、同じシンタックスを使っているクエリ内で使用できます。

## 9.3. Map のインデックスとしてのコンポーネント

`<composite-map-key>` 要素は `Map` のキーとしてコンポーネントクラスをマッピングします。コンポーネントクラス上で `hashCode()` と `equals()` を正確にオーバーライドしてください。

## 9.4. 複合識別子としてのコンポーネント

コンポーネントをエンティティクラスの識別子として使うことができます。コンポーネントクラスは以下の条件を満たす必要があります。

- `java.io.Serializable` を実装しなければなりません。

- データベース上の複合キーの等価性と矛盾のないように、 `equals()` と `hashCode()` を再実装しなければなりません。

## 注記

Hibernate3 において、2番目の条件は絶対的な条件ではありません。それでもやはり条件を満たしてください。

複合キーを生成するために `IdentifierGenerator` を使用することはできません。代わりにアプリケーションが識別子を割り当てなくてはなりません。

通常の `<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

    >

このとき、 `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

    >

## ティップ

The `column` element is an alternative to the `column` attribute everywhere. Using the `column` element just gives more declaration options, which are mostly useful when utilizing `hbm2ddl`

`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

    >

`Order` にある `OrderLine` のコレクションは次のものを使用します。

    <set name="orderLines" inverse="true">

        <key>

            <column name="orderId"/>

            <column name="customerId"/>

        </key>

        <one-to-many class="OrderLine"/>

    </set

    >

（`<one-to-many>` 属性は、例によってカラムを宣言しません）

`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

    >

## 9.5. 動的コンポーネント

`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

    >

`<dynamic-component>` マッピングのセマンティクスは `<component>` と同一のものです。この種のマッピングの利点は、マッピングドキュメントの編集により、配置時に Bean の属性を決定できる点です。また、 DOM パーサを利用して、マッピングドキュメントのランタイム操作が可能です。さらに、 `Configuration` オブジェクト経由で Hibernate のコンフィグレーション時のメタモデルにアクセス（または変更）が可能です。

## 第10章 継承マッピング

## 10.1. 3つの戦略

Hibernate は3つの基本的な継承のマッピング戦略をサポートします。

- クラス階層ごとのテーブル （table-per-class-hierarchy）

- table per subclass

- 具象クラスごとのテーブル （table-per-concrete-class）

加えて4つ目に、 Hibernate はわずかに異なる性質を持ったポリモーフィズムをサポートします。

- 暗黙的ポリモーフィズム

同一の継承階層の異なるブランチに対して異なるマッピング戦略を使うことができます。その場合には全体の階層に渡るポリモーフィズムを実現するために暗黙的ポリモーフィズムを使用します。しかし、 Hibernate は同じルート `<class>` 要素内で `<subclass>` マッピング、 `<joined-subclass>` マッピング、 `<union-subclass>` マッピングの同時使用をサポートしていません。 `<subclass>` 要素と `<join>` 要素を組み合わせることで、同一 `<class>` 要素内での table-per-hierarchy 戦略と table-per-subclass 戦略の同時使用は可能です。次の例を見てください。

`subclass`、 `union-subclass` と `joined-subclass` マッピングを複数のマッピングドキュメントに定義することが出来、 `hibernate-mapping` の直下に配置します。これは新しいマッピングファイルを追加するだけで、クラス階層を拡張できるということです。あらかじめマップしたスーパークラスを指定して、サブクラスマッピングに `extends` 属性を記述しなければなりません。注記：この特徴により、以前はマッピングドキュメントの順番が重要でした。 Hibernate3 からは、 extends キーワードを使う場合、マッピングドキュメントの順番は問題になりません。１つのマッピングファイル内で順番付けを行うときは、依然として、サブクラスを定義する前にスーパークラスを定義する必要があります。)

     <hibernate-mapping>

         <subclass name="DomesticCat" extends="Cat" discriminator-value="D">

              <property name="name" type="string"/>

         </subclass>

     </hibernate-mapping

    >

### 10.1.1. クラス階層ごとのテーブル（table-per-class-hierarchy）

例えば、インターフェース `Payment` と、それを実装した `CreditCardPayment`、 `CashPayment`、 `ChequePayment` があるとします。階層ごとのテーブルマッピングは以下のようになります:

    <class name="Payment" table="PAYMENT">

        <id name="id" type="long" column="PAYMENT_ID">

            <generator class="native"/>

        </id>

        <discriminator column="PAYMENT_TYPE" type="string"/>

        <property name="amount" column="AMOUNT"/>

        ...

        <subclass name="CreditCardPayment" discriminator-value="CREDIT">

            <property name="creditCardType" column="CCTYPE"/>

            ...

        </subclass>

        <subclass name="CashPayment" discriminator-value="CASH">

            ...

        </subclass>

        <subclass name="ChequePayment" discriminator-value="CHEQUE">

            ...

        </subclass>

    </class

    >

ちょうど一つのテーブルが必要です。このマッピング戦略には一つ大きな制限があります。 `CCTYPE` のような、サブクラスで宣言されたカラムは `NOT NULL` 制約を持てません。

### 10.1.2. サブクラスごとのテーブル （table-per-subclass）

table-per-subclass マッピングは以下のようになります:

    <class name="Payment" table="PAYMENT">

        <id name="id" type="long" column="PAYMENT_ID">

            <generator class="native"/>

        </id>

        <property name="amount" column="AMOUNT"/>

        ...

        <joined-subclass name="CreditCardPayment" table="CREDIT_PAYMENT">

            <key column="PAYMENT_ID"/>

            <property name="creditCardType" column="CCTYPE"/>

            ...

        </joined-subclass>

        <joined-subclass name="CashPayment" table="CASH_PAYMENT">

            <key column="PAYMENT_ID"/>

            ...

        </joined-subclass>

        <joined-subclass name="ChequePayment" table="CHEQUE_PAYMENT">

            <key column="PAYMENT_ID"/>

            ...

        </joined-subclass>

    </class

    >

このマッピングには4つのテーブルが必要です。3つのサブクラステーブルはスーパークラステーブルとの関連を示す主キーを持っています （実際、関係モデル上は一対一関連です）。

### 10.1.3. discriminator を用いた table-per-subclass

Hibernate の table-per-subclass 実装は、 discriminator カラムを必要としないことを覚えておいてください。 Hibernate 以外の O/R マッパーは、 table-per-subclass に異なる実装を用います。それは、スーパークラスのテーブルにタイプ discriminator カラムを必要とします。このアプローチは実装が困難になりますが、関係の視点から見ると、より正確なものです。 table-per-subclass 戦略で discriminator カラムを使いたければ、 `<subclass>` と `<join>` を以下のように組み合わせて使ってください。

    <class name="Payment" table="PAYMENT">

        <id name="id" type="long" column="PAYMENT_ID">

            <generator class="native"/>

        </id>

        <discriminator column="PAYMENT_TYPE" type="string"/>

        <property name="amount" column="AMOUNT"/>

        ...

        <subclass name="CreditCardPayment" discriminator-value="CREDIT">

            <join table="CREDIT_PAYMENT">

                <key column="PAYMENT_ID"/>

                <property name="creditCardType" column="CCTYPE"/>

                ...

            </join>

        </subclass>

        <subclass name="CashPayment" discriminator-value="CASH">

            <join table="CASH_PAYMENT">

                <key column="PAYMENT_ID"/>

                ...

            </join>

        </subclass>

        <subclass name="ChequePayment" discriminator-value="CHEQUE">

            <join table="CHEQUE_PAYMENT" fetch="select">

                <key column="PAYMENT_ID"/>

                ...

            </join>

        </subclass>

    </class

    >

オプションの `fetch="select"` 宣言は、スーパークラスのクエリ実行時に外部結合を使って、サブクラスの `ChequePayment` データを取得しないように指定するためのものです。

### 10.1.4. table-per-subclass と table-per-class-hierarchy の混合

このアプローチを使用すると、 table-per-hierarchy と table-per-subclass 戦略を組み合わせる事も可能です。

    <class name="Payment" table="PAYMENT">

        <id name="id" type="long" column="PAYMENT_ID">

            <generator class="native"/>

        </id>

        <discriminator column="PAYMENT_TYPE" type="string"/>

        <property name="amount" column="AMOUNT"/>

        ...

        <subclass name="CreditCardPayment" discriminator-value="CREDIT">

            <join table="CREDIT_PAYMENT">

                <property name="creditCardType" column="CCTYPE"/>

                ...

            </join>

        </subclass>

        <subclass name="CashPayment" discriminator-value="CASH">

            ...

        </subclass>

        <subclass name="ChequePayment" discriminator-value="CHEQUE">

            ...

        </subclass>

    </class

    >

いずれのマッピング戦略であっても、ルートである `Payment` クラスへのポリモーフィックな関連は `<many-to-one>` を使ってマッピングします。

    <many-to-one name="payment" column="PAYMENT_ID" class="Payment"/>

### 10.1.5. 具象クラスごとのテーブル（table-per-concrete-class）

table-per-concrete-class 戦略のマッピングに対するアプローチは、2つあります。1つ目は `<union-subclass>` を利用する方法です。

    <class name="Payment">

        <id name="id" type="long" column="PAYMENT_ID">

            <generator class="sequence"/>

        </id>

        <property name="amount" column="AMOUNT"/>

        ...

        <union-subclass name="CreditCardPayment" table="CREDIT_PAYMENT">

            <property name="creditCardType" column="CCTYPE"/>

            ...

        </union-subclass>

        <union-subclass name="CashPayment" table="CASH_PAYMENT">

            ...

        </union-subclass>

        <union-subclass name="ChequePayment" table="CHEQUE_PAYMENT">

            ...

        </union-subclass>

    </class

    >

サブクラスごとに3つのテーブルが必要です。それぞれのテーブルは、継承プロパティを含んだ、クラスの全てのプロパティに対するカラムを定義します。

The limitation of this approach is that if a property is mapped on the superclass, the column name must be the same on all subclass tables. The identity generator strategy is not allowed in union subclass inheritance. The primary key seed has to be shared across all unioned subclasses of a hierarchy.

もしスーパークラスが抽象クラスなら、 `abstract="true"` とマッピングします。もちろん、スーパークラスが抽象クラスでないなら、スーパークラスのインスタンスを保持するためのテーブルの追加が必要となります (上の例でのデフォルトは `PAYMENT` )。

### 10.1.6. 暗黙的ポリモーフィズムを用いた table-per-concrete-class

もう一つのアプローチは暗黙的ポリモーフィズムの使用です：

    <class name="CreditCardPayment" table="CREDIT_PAYMENT">

        <id name="id" type="long" column="CREDIT_PAYMENT_ID">

            <generator class="native"/>

        </id>

        <property name="amount" column="CREDIT_AMOUNT"/>

        ...

    </class>

    <class name="CashPayment" table="CASH_PAYMENT">

        <id name="id" type="long" column="CASH_PAYMENT_ID">

            <generator class="native"/>

        </id>

        <property name="amount" column="CASH_AMOUNT"/>

        ...

    </class>

    <class name="ChequePayment" table="CHEQUE_PAYMENT">

        <id name="id" type="long" column="CHEQUE_PAYMENT_ID">

            <generator class="native"/>

        </id>

        <property name="amount" column="CHEQUE_AMOUNT"/>

        ...

    </class

    >

`Payment` インターフェースがどこにも明示的に示されていないことに注意してください。そして、 `Payment` プロパティがそれぞれのサブクラスにマッピングされていることにも注意してください。もし重複を避けたいのであれば、 XML エンティティの利用を考えてください。 （例： `DOCTYPE` 宣言における `[ <!ENTITY allproperties SYSTEM "allproperties.xml"> ]` と、マッピングにおける `&allproperties;`）。

このアプローチの欠点は、 Hibernate がポリモーフィックなクエリの実行時に SQL `UNION` を生成しない点です。

このマッピング戦略に対しては、 `Payment` へのポリモーフィックな関連は常に、 `<any>` を使ってマッピングされます。

    <any name="payment" meta-type="string" id-type="long">

        <meta-value value="CREDIT" class="CreditCardPayment"/>

        <meta-value value="CASH" class="CashPayment"/>

        <meta-value value="CHEQUE" class="ChequePayment"/>

        <column name="PAYMENT_CLASS"/>

        <column name="PAYMENT_ID"/>

    </any

    >

### 10.1.7. 他の継承マッピングと暗黙的ポリモーフィズムの組み合わせ

このマッピングについての更なる注意点があります。サブクラスが自身を `<class>` 要素としてマッピングしているので、（かつ `Payment` は単なるインターフェースなので）、それぞれのサブクラスは簡単にその他の継承階層の一部となります。（しかも、今までどおり `Payment` インターフェースに対するポリモーフィックなクエリを使用することができます）

    <class name="CreditCardPayment" table="CREDIT_PAYMENT">

        <id name="id" type="long" column="CREDIT_PAYMENT_ID">

            <generator class="native"/>

        </id>

        <discriminator column="CREDIT_CARD" type="string"/>

        <property name="amount" column="CREDIT_AMOUNT"/>

        ...

        <subclass name="MasterCardPayment" discriminator-value="MDC"/>

        <subclass name="VisaPayment" discriminator-value="VISA"/>

    </class>

    <class name="NonelectronicTransaction" table="NONELECTRONIC_TXN">

        <id name="id" type="long" column="TXN_ID">

            <generator class="native"/>

        </id>

        ...

        <joined-subclass name="CashPayment" table="CASH_PAYMENT">

            <key column="PAYMENT_ID"/>

            <property name="amount" column="CASH_AMOUNT"/>

            ...

        </joined-subclass>

        <joined-subclass name="ChequePayment" table="CHEQUE_PAYMENT">

            <key column="PAYMENT_ID"/>

            <property name="amount" column="CHEQUE_AMOUNT"/>

            ...

        </joined-subclass>

    </class

    >

もう一度述べますが、 `Payment` は明示的に定義されません。もし、 `Payment` インターフェースに対してクエリを実行するなら （例えば `from Payment` 節を使って）、 Hibernate は自動的に `CreditCardPayment` （と CreditCardPayment のサブクラス、 `Payment` の実装であるため）、および、 `CashPayment` 、 `ChequePayment` のインスタンスを返します。 `NonelectronicTransaction` インスタンスは返しません。

## 10.2. 制限

table-per-concrete-class マッピング戦略への「暗黙的ポリモーフィズム」アプローチにはいくつかの制限があります。 `<union-subclass>` マッピングに対しても少し弱めの制限があります。

The following table shows the limitations of table per concrete-class mappings, and of implicit polymorphism, in Hibernate.

表10.1 継承マッピングの機能

継承戦略 | Polymorphic many-to-one | 一対一のポリモーフィズム | 一対多のポリモーフィズム | 多対多のポリモーフィズム | ポリモーフィックな `load()/get()` | ポリモーフィズムを使ったクエリ | ポリモーフィズムを使った結合 | Outer join fetching
--- | --- | --- | --- | --- | --- | --- | --- | ---
table per class-hierarchy | `<many-to-one>` | `<one-to-one>` | `<one-to-many>` | `<many-to-many>` | `s.get(Payment.class, id)` | `from Payment p` | `from Order o join o.payment p` | supported
table per subclass | `<many-to-one>` | `<one-to-one>` | `<one-to-many>` | `<many-to-many>` | `s.get(Payment.class, id)` | `from Payment p` | `from Order o join o.payment p` | supported
table per concrete-class (union-subclass) | `<many-to-one>` | `<one-to-one>` | `<one-to-many>` (for `inverse="true"` only) | `<many-to-many>` | `s.get(Payment.class, id)` | `from Payment p` | `from Order o join o.payment p` | supported
table per concrete class (implicit polymorphism) | `<any>` | not supported | not supported | `<many-to-any>` | `s.createCriteria(Payment.class).add( Restrictions.idEq(id) ).uniqueResult()` | `from Payment p` | not supported | not supported

## 第11章 オブジェクトを扱う

Hibernate は完全なオブジェクト/リレーショナルマッピングソリューションであり、データベース管理システムの詳細を開発者から隠蔽するだけでなく、オブジェクトの 状態管理 も行います。これは、 JDBC/SQL 永続層と同じような SQL `statements` の管理とは異なり、 Java アプリケーションにおける永続化に対する、とても自然なオブジェクト指向の考え方を提供します。

言いかえれば、 Hibernate を用いるアプリケーション開発者は、オブジェクトの 状態 については常に意識すべきであり、 SQL 文の実行については必ずしもそうではありません。この部分は、通常、 Hibernate が処理し、システムのパフォーマンスをチューニングするときにだけ、問題になってきます。

## 11.1. Hibernate におけるオブジェクトの状態

Hibernate は次のようなオブジェクトの状態を定義し、サポートしています:

- Transient - `new` 演算子を使ってインスタンス化されただけで、 Hibernate の `Session` に関連付けられていないオブジェクトは、 transient です。それは、データベースに永続的な表現を持たず、識別子となる値は割り当てられていません。 Transient インスタンスは、アプリケーションがその参照をどこにも保持しない場合に、ガベージコレクタによって破棄されます。オブジェクトを永続的 (persistent) な状態にするためには、 Hibernate の `Session` を使いましょう（この状態遷移に必要となる SQL 文の発行は、 Hibernate に任せましょう）。

- 永続的 (Persistent) - 永続的なインスタンスはデータベースに永続的な表現を持ち、識別子となる値を持っています。それは、セーブされたり、ロードされたりするかもしれませんが、定義上は、 `Session` のスコープの中に存在しています。 Hibernate は、作業単位（Unit of Work）が完了したときに、永続状態のオブジェクトに加えられた変更を検出し、オブジェクトの状態とデータベースを同期します。オブジェクトを transient にするときは、開発者は、手作業で `UPDATE` 文や `DELETE` 文を実行しません。

- Detached - detached インスタンスとは、永続化されているが、それと関連付いていた `Session` がクローズされているオブジェクトのことです。そのオブジェクトへの参照は、依然として有効です。そして、もちろん、detached インスタンスはこの状態に修正することさえできます。 detached インスタンスは、もう一度永続化したい（そして、すべての変更を永続化したい）ときに、新しい `Session` に再追加できます。この機能は、ユーザーが考える時間を必要とするような、長期間に及ぶ作業単位に対するプログラミングモデルを可能にします。我々は、これを アプリケーションのトランザクション（application transactions） と呼んでいます。すなわち、ユーザーから見た作業単位だということです。

これから、状態と状態遷移（そして、遷移のきっかけとなる Hibernate のメソッド）について、詳細に述べます。

## 11.2. オブジェクトを永続状態にする

Newly instantiated instances of a persistent class are considered transient by Hibernate. We can make a transient instance persistent by associating it with a session:

    DomesticCat fritz = new DomesticCat();

    fritz.setColor(Color.GINGER);

    fritz.setSex('M');

    fritz.setName("Fritz");

    Long generatedId = (Long) sess.save(fritz);

`Cat` クラスの識別子が自動生成されるのであれば、 `save()` が呼ばれるときに、識別子が生成され、 `cat` インスタンスに割り当てられます。 `Cat` の識別子が `assigned` 識別子を持つか、複合キーであるなら、 `save()` を呼び出す前に、識別子を `cat` インスタンスを割り当てなければなりません。 `save()` の代わりに、 EJB3 の初期ドラフトで定義された `persist()` を使うことも可能です。

- `persist()` makes a transient instance persistent. However, it does not guarantee that the identifier value will be assigned to the persistent instance immediately, the assignment might happen at flush time. `persist()` also guarantees that it will not execute an `INSERT` statement if it is called outside of transaction boundaries. This is useful in long-running conversations with an extended Session/persistence context.

- `save()` does guarantee to return an identifier. If an INSERT has to be executed to get the identifier ( e.g. "identity" generator, not "sequence"), this INSERT happens immediately, no matter if you are inside or outside of a transaction. This is problematic in a long-running conversation with an extended Session/persistence context.

Alternatively, you can assign the identifier using an overloaded version of `save()`.

    DomesticCat pk = new DomesticCat();

    pk.setColor(Color.TABBY);

    pk.setSex('F');

    pk.setName("PK");

    pk.setKittens( new HashSet() );

    pk.addKitten(fritz);

    sess.save( pk, new Long(1234) );

永続化するオブジェクトが関連オブジェクトを持っている場合 （例えば、前の例における `kittens` コレクションのように）、外部キーカラムに、 `NOT NULL` 制約をつけない限りは、これらの一連のオブジェクトをどんな順番で永続化してもかまいません。外部キー制約を違反する恐れはありません。しかし、 `NOT NULL` 制約がある場合、間違った順番でオブジェクトを `save()` してしまうと、制約に違反するかもしれません。

関連するオブジェクトを自動的に保存する、 Hibernate の 遷移的な永続化 (transitive persistence) 機能を使うつもりならば、そのような詳細を気にする必要はありません。そして、 `NOT NULL` 制約の違反すら起こりません。 Hibernate がすべて面倒をみてくれます。遷移的な永続化は、この章の後半に書かれています。

## 11.3. オブジェクトのロード

永続化されたインスタンスの識別子があらかじめ分かっているなら、 `Session` の `load()` メソッドを使って、復元できます。 `load()` は、 Class オブジェクトを引数にとり、そのクラスのインスタンスを新たに生成し、状態をロードします。そのインスタンスの状態は、永続 (persistent) 状態です。

    Cat fritz = (Cat) sess.load(Cat.class, generatedId);

    // you need to wrap primitive identifiers

    long id = 1234;

    DomesticCat pk = (DomesticCat) sess.load( DomesticCat.class, new Long(id) );

あるいは、以下のように、既存のインスタンスに状態をロードすることもできます:

    Cat cat = new DomesticCat();

    // load pk's state into cat

    sess.load( cat, new Long(pkId) );

    Set kittens = cat.getKittens();

DB に該当する行が無い場合、 `load()` は回復不可能な例外を投げることに注意しましょう。そのクラスがプロキシを使ってマッピングされている場合、 `load()` は初期化されていないプロキシを返し、プロキシのメソッドが呼ばれるまで実際にはデータベースにアクセスしません。もし、実際にデータベースからロードせずに、オブジェクトに対する関連を作りたい場合、この振る舞いはとても役立ちます。 `batch-size` がクラスマッピングに定義されているならば、複数のインスタンスを一括でロードすることが可能です。

該当する行が存在することを確信できない場合は、 `get()` メソッドを使うべきです。それは、データベースにすぐにアクセスし、該当する行が無い場合は null を返します。

    Cat cat = (Cat) sess.get(Cat.class, id);

    if (cat==null) {

        cat = new Cat();

        sess.save(cat, id);

    }

    return cat;

`LockMode` を使えば、 `SELECT ... FOR UPDATE` という SQL を使ってオブジェクトをロードすることができます。詳細な情報は、 API ドキュメントを参照してください。

    Cat cat = (Cat) sess.get(Cat.class, id, LockMode.UPGRADE);

関連に対するカスケード方法として `lock` や `all` を指定しない限り、関連するインスタンスや含まれるコレクションは `FOR UPDATE` で復元 されない ことに注意しましょう。

`refresh()` メソッドを使うことで、どんなときでも、オブジェクトやそのコレクションをリロードすることができます。データベースのトリガがテーブルを更新した際に、そのテーブルに対応するオブジェクトのプロパティを同期する場合、このメソッドが役に立ちます。

    sess.save(cat);

    sess.flush(); //force the SQL INSERT

    sess.refresh(cat); //re-read the state (after the trigger executes)

How much does Hibernate load from the database and how many SQL `SELECT`s will it use? This depends on the fetching strategy. This is explained in 「フェッチ戦略」.

## 11.4. クエリ

探したいオブジェクトの識別子が分からない場合は、クエリが必要になります。 Hibernate は使いやすくて強力なオブジェクト指向のクエリ言語 (HQL) をサポートしています。プログラムによってクエリが作成できるように、 Hibernate は洗練された Criteria と Example クエリ機能 (QBC と QBE） をサポートしています。 ResultSet をオブジェクトに変換する Hibernate のオプション機能を使うことで、データベースのネイティブな SQL でクエリを表現することもできます。

### 11.4.1. クエリの実行

HQL やネイティブな SQL クエリは、 `org.hibernate.Query` のインスタンスとして表現されます。このインタフェースは、パラメータバインディングや ResultSet のハンドリングやクエリの実行を行うメソッドを用意しています。通常、 `Query` は、以下に示すように、その時点の `Session` を使って取得します。

    List cats = session.createQuery(

        "from Cat as cat where cat.birthdate < ?")

        .setDate(0, date)

        .list();

    List mothers = session.createQuery(

        "select mother from Cat as cat join cat.mother as mother where cat.name = ?")

        .setString(0, name)

        .list();

    List kittens = session.createQuery(

        "from Cat as cat where cat.mother = ?")

        .setEntity(0, pk)

        .list();

    Cat mother = (Cat) session.createQuery(

        "select cat.mother from Cat as cat where cat = ?")

        .setEntity(0, izi)

        .uniqueResult();]]

    Query mothersWithKittens = (Cat) session.createQuery(

        "select mother from Cat as mother left join fetch mother.kittens");

    Set uniqueMothers = new HashSet(mothersWithKittens.list());

クエリは、普通、 `list()` を呼び出すことによって実行されます。クエリの結果は、メモリ上にあるコレクションにすべてロードされます。クエリによって復元されたエンティティのインスタンスは、永続状態です。もし、クエリがたった1個のインスタンスを返すと分かっているなら、 `uniqueResult()` メソッドが手っ取り早い方法です。即時フェッチを利用したクエリの場合、ふつう、得られたコレクションには、ルートのオブジェクトが重複して含まれています（しかし、ルートが持つコレクションは初期化 (ロード）されています）。この重複は `Set` を使って取り除くことができます。

#### 11.4.1.1. 結果をイテレートする

時々、 `iterate()` メソッドを使ってクエリを実行することで、より良いパフォーマンスを得ることができます。これは、通常、クエリによって得られた実際のエンティティのインスタンスが、すでにセッションまたは二次キャッシュに存在することが期待できる場合だけです。それらが、まだキャッシュされていないなら、 `iterate()` は、 `list()` よりも遅く、簡単なクエリに対しても多くのデータベースアクセスを必要とします。そのアクセスとは、識別子だけを取得するための最初の select １回 と、実際のインスタンスを初期化するために後から行う n回 の select のことです。

    // fetch ids

    Iterator iter = sess.createQuery("from eg.Qux q order by q.likeliness").iterate();

    while ( iter.hasNext() ) {

        Qux qux = (Qux) iter.next();  // fetch the object

        // something we couldnt express in the query

        if ( qux.calculateComplicatedAlgorithm() ) {

            // delete the current instance

            iter.remove();

            // dont need to process the rest

            break;

        }

    }

#### 11.4.1.2. オブジェクトの組（tuple）を返すクエリ

Hibernate のクエリでは、時々、オブジェクトの組を返すことがあります。その場合は、各タプルは配列として返されます:

    Iterator kittensAndMothers = sess.createQuery(

                "select kitten, mother from Cat kitten join kitten.mother mother")

                .list()

                .iterator();

    while ( kittensAndMothers.hasNext() ) {

        Object[] tuple = (Object[]) kittensAndMothers.next();

        Cat kitten = (Cat) tuple[0];

        Cat mother = (Cat) tuple[1];

        ....

    }

#### 11.4.1.3. スカラーの結果

クエリでは、 `select` 節でクラスのプロパティを指定できます。 SQL の集合関数を呼ぶこともできます。プロパティや集合関数は、（永続状態のエンティティではなく）「スカラー値」であると見なされます。

    Iterator results = sess.createQuery(

            "select cat.color, min(cat.birthdate), count(cat) from Cat cat " +

            "group by cat.color")

            .list()

            .iterator();

    while ( results.hasNext() ) {

        Object[] row = (Object[]) results.next();

        Color type = (Color) row[0];

        Date oldest = (Date) row[1];

        Integer count = (Integer) row[2];

        .....

    }

#### 11.4.1.4. パラメータのバインド

`Query` は、名前付きのパラメータや JDBC スタイルの `?` パラメータに値をバインドするためのメソッドを持っています。 JDBC とは違い、 Hibernate はパラメータにゼロから番号を振っていきます。名前付きのパラメータとは、クエリ文字列のなかにある `:name` 形式の識別子です。名前付きパラメータの利点は次の通りです。

- 名前付きパラメータは、クエリ文字列に登場する順番と無関係です

- 同じクエリ内に複数回登場することができます

- 自分自身を説明します

    //named parameter (preferred)

    Query q = sess.createQuery("from DomesticCat cat where cat.name = :name");

    q.setString("name", "Fritz");

    Iterator cats = q.iterate();

    //positional parameter

    Query q = sess.createQuery("from DomesticCat cat where cat.name = ?");

    q.setString(0, "Izi");

    Iterator cats = q.iterate();

    //named parameter list

    List names = new ArrayList();

    names.add("Izi");

    names.add("Fritz");

    Query q = sess.createQuery("from DomesticCat cat where cat.name in (:namesList)");

    q.setParameterList("namesList", names);

    List cats = q.list();

#### 11.4.1.5. ページ分け

ResultSet に制限（復元したい最大行数や復元したい最初の行）を加える必要があれば、以下のように、 `Query` インターフェースのメソッドを使います。

    Query q = sess.createQuery("from DomesticCat cat");

    q.setFirstResult(20);

    q.setMaxResults(10);

    List cats = q.list();

制限付きのクエリを DBMS のネイティブな SQL に変換する方法を、 Hibernate は知っています。

#### 11.4.1.6. スクロール可能なイテレーション

JDBC ドライバがスクロール可能な `ResultSet` をサポートしていれば、 `Query` インターフェースを使って、 `ScrollableResults` オブジェクトを取得できます。それを使うと、クエリの結果に対して柔軟にナビゲーションできます。

    Query q = sess.createQuery("select cat.name, cat from DomesticCat cat " +

                                "order by cat.name");

    ScrollableResults cats = q.scroll();

    if ( cats.first() ) {

        // find the first name on each page of an alphabetical list of cats by name

        firstNamesOfPages = new ArrayList();

        do {

            String name = cats.getString(0);

            firstNamesOfPages.add(name);

        }

        while ( cats.scroll(PAGE_SIZE) );

        // Now get the first page of cats

        pageOfCats = new ArrayList();

        cats.beforeFirst();

        int i=0;

        while( ( PAGE_SIZE > i++ ) && cats.next() ) pageOfCats.add( cats.get(1) );

    }

    cats.close()

この機能にはオープン状態のデータベースコネクションが必要であることに注意してください。もし、オフラインのページ分け機能が必要であれば、 `setMaxResult()` / `setFirstResult()` を使いましょう。

#### 11.4.1.7. 名前付きクエリの外出し

Queries can also be configured as so called named queries using annotations or Hibernate mapping documents. `@NamedQuery` and `@NamedQueries` can be defined at the class level as seen in 例11.1「Defining a named query using @NamedQuery」 . However their definitions are global to the session factory/entity manager factory scope. A named query is defined by its name and the actual query string.

例11.1 Defining a named query using `@NamedQuery`

    @Entity

    @NamedQuery(name="night.moreRecentThan", query="select n from Night n where n.date >= :date")

    public class Night {

        ...

    }

    public class MyDao {

        doStuff() {

            Query q = s.getNamedQuery("night.moreRecentThan");

            q.setDate( "date", aMonthAgo );

            List results = q.list();

            ...

        }

        ...

    }

Using a mapping document can be configured using the `<query>` node. Remember to use a `CDATA` section if your query contains characters that could be interpreted as markup.

例11.2 Defining a named query using `<query>`

    <query name="ByNameAndMaximumWeight"><![CDATA[

        from eg.DomesticCat as cat

            where cat.name = ?

            and cat.weight > ?

    ] ]></query>

Parameter binding and executing is done programatically as seen in 例11.3「Parameter binding of a named query」.

例11.3 Parameter binding of a named query

    Query q = sess.getNamedQuery("ByNameAndMaximumWeight");

    q.setString(0, name);

    q.setInt(1, minWeight);

    List cats = q.list();

実際のプログラムコードは、使われるクエリ言語に依存していないことに注意しましょう。メタデータには、ネイティブ SQL クエリを定義することもできます。また、既存のクエリをマッピングファイルに移すことで、 Hibernate に移行することもできます。

`<hibernate-mapping>` 要素の中のクエリ定義は、クエリに対するユニークな名前が必要なことにも注意してください。それに対して、 `<class>` 要素の中のクエリ定義は、クラスの完全限定名が前に付けられるので、自動的にユニークな名前になります。例： `eg.Cat.ByNameAndMaximumWeight`

### 11.4.2. フィルタリングコレクション

コレクション フィルタ は、永続化されているコレクションや配列に適用される特殊なタイプのクエリです。そのクエリ文字列では、コレクションのその時点での要素を意味する `this` を使います。

    Collection blackKittens = session.createFilter(

        pk.getKittens(),

        "where this.color = ?")

        .setParameter( Color.BLACK, Hibernate.custom(ColorUserType.class) )

        .list()

    );

返されるコレクションは Bag とみなされます。そして、それはもとのコレクションのコピーになります。元のコレクションは修正されません（これは、 "filter" という名前の意味とは異なりますが、期待される動きとは一致しています）。

フィルタには `from` 節が不要であることに気づくでしょう（必要なら、持つことも可能ですが）。フィルタは、コレクションの要素自体を返して構いません。

    Collection blackKittenMates = session.createFilter(

        pk.getKittens(),

        "select this.mate where this.color = eg.Color.BLACK.intValue")

        .list();

クエリを含まないフィルタも役に立ちます。例えば、非常に大きなコレクションの部分集合をロードするために使えます。

    Collection tenKittens = session.createFilter(

        mother.getKittens(), "")

        .setFirstResult(0).setMaxResults(10)

        .list();

### 11.4.3. クライテリアのクエリ

HQL は非常に強力ですが、クエリ文字列を作るよりも、オブジェクト指向の API を使って動的にクエリを作る方を好む開発者もいます。こういった場合のために、 Hibernate は直感的な `Criteria` クエリ API を提供しています。

    Criteria crit = session.createCriteria(Cat.class);

    crit.add( Restrictions.eq( "color", eg.Color.BLACK ) );

    crit.setMaxResults(10);

    List cats = crit.list();

The `Criteria` and the associated `Example` API are discussed in more detail in 17章Criteria クエリ.

### 11.4.4. ネイティブ SQL のクエリ

`createSQLQuery()` を使って、 SQL でクエリを表現することもできます。そして、 Hibernate に、 ResultSet からオブジェクトへのマッピングをまかせます。 `session.connection()` を呼べばどんなときでも、直接、 JDBC `Connection` を使用できることを覚えておきましょう。もし、 Hibernate API を使うのであれば、下記のように SQL の別名を括弧でくくらなければなりません。

    List cats = session.createSQLQuery("SELECT {cat.*} FROM CAT {cat} WHERE ROWNUM<10")

        .addEntity("cat", Cat.class)

    .list();

    List cats = session.createSQLQuery(

        "SELECT {cat}.ID AS {cat.id}, {cat}.SEX AS {cat.sex}, " +

               "{cat}.MATE AS {cat.mate}, {cat}.SUBCLASS AS {cat.class}, ... " +

        "FROM CAT {cat} WHERE ROWNUM<10")

        .addEntity("cat", Cat.class)

    .list()

SQL queries can contain named and positional parameters, just like Hibernate queries. More information about native SQL queries in Hibernate can be found in 18章ネイティブ SQL.

## 11.5. 永続オブジェクトの修正

処理中の永続インスタンス （例： `Session` によって、ロード、セーブ、作成、クエリされたオブジェクト）は、アプリケーションに操作されます。その際に変更された永続状態は、 `Session` が フラッシュ されるときに、永続化されます（これは、この章の後半で述べています）。変更を永続化するために、特殊なメソッド（ `update()` のようなもの。これは、別の目的で使用します）を呼ぶ必要はありません。オブジェクトの状態を更新する一番簡単な方法は、オブジェクトを `load()` し、 `Session` をオープンにしている間に、直接操作することです。

    DomesticCat cat = (DomesticCat) sess.load( Cat.class, new Long(69) );

    cat.setName("PK");

    sess.flush();  // changes to cat are automatically detected and persisted

（オブジェクトをロードするための） SQL の `SELECT` と（更新された状態を永続化するための） SQL の `UPDATE` が同じセッションで必要となるので、このプログラミングモデルは、効率が悪くなる場合があります。そのため、 Hibernate は別の方法を用意しています。それは、 detached インスタンスを使用する方法です。

## 11.6. detached オブジェクトの修正

多くのアプリケーションでは次のことが必要になります。それは、あるトランザクションでオブジェクトを復元し、操作するためにそれを UI 層に送り、その後に、新しいトランザクションで変更をセーブするといったことです。並行性の高い環境で、このタイプのアプローチを使うアプリケーションでは、「期間の長い」作業単位の隔離性を保証するために、バージョンデータが通常使われます。

Hibernate は、 `Session.update()` や `Session.merge()` メソッドを使って、 detached インスタンスを再追加することで、このモデルに対応します。

    // in the first session

    Cat cat = (Cat) firstSession.load(Cat.class, catId);

    Cat potentialMate = new Cat();

    firstSession.save(potentialMate);

    // in a higher layer of the application

    cat.setMate(potentialMate);

    // later, in a new session

    secondSession.update(cat);  // update cat

    secondSession.update(mate); // update mate

識別子 `catId` を持つ `Cat` が、既に `secondSession` でロードされていた場合は、再追加しようとしたときに、例外が投げられます。

同じ識別子を持つ永続インスタンスをセッションが既に保持していないことを確信できるなら `update()` を使います。そして、セッションの状態を考えずに、どんな場合でも変更をマージしたい場合は、 `merge()` を使います。すなわち、 detached インスタンスの再追加操作が、最初に実行されることを確実にするために、通常は `update()` が新しいセッションのなかで最初に呼ばれるメソッドになります。

The application should individually `update()` detached instances that are reachable from the given detached instance only if it wants their state to be updated. This can be automated using transitive persistence. See 「連鎖的な永続化」 for more information.

`lock()` メソッドでもまた、新しいセッションにオブジェクトを再関連付けできます。しかし、 detached インスタンスは無修正でなければなりません。

    //just reassociate:

    sess.lock(fritz, LockMode.NONE);

    //do a version check, then reassociate:

    sess.lock(izi, LockMode.READ);

    //do a version check, using SELECT ... FOR UPDATE, then reassociate:

    sess.lock(pk, LockMode.UPGRADE);

`lock()` は、さまざまな `LockMode` とともに使うことができます。詳細は、 API ドキュメントとトランザクション処理の章を参照してください。再追加のときにだけ、 `lock()` が使われるわけではありません。

Other models for long units of work are discussed in 「楽観的同時実行制御」.

## 11.7. 自動的な状態検出

Hibernate のユーザーは次の2つのケースのどちらにも使える汎用的なメソッドを要求していました。それは、新しい識別子を生成して transient インスタンスをセーブすることと、その時点の識別子と関連づいている detached インスタンスを更新/再追加することのできるメソッドです。 `saveOrUpdate()` はこのような機能を実現したメソッドです。

    // in the first session

    Cat cat = (Cat) firstSession.load(Cat.class, catID);

    // in a higher tier of the application

    Cat mate = new Cat();

    cat.setMate(mate);

    // later, in a new session

    secondSession.saveOrUpdate(cat);   // update existing state (cat has a non-null id)

    secondSession.saveOrUpdate(mate);  // save the new instance (mate has a null id)

`saveOrUpdate()` の使用方法と意味は、新しいユーザーにとって混乱を招くかもしれません。まず第一に、あるセッションで使用したインスタンスを別の新しいセッションで使おうとしない限り、 `update()` や `saveOrUpdate()` や `merge()` を使う必要はありません。アプリケーション全体を通じて、これらのメソッドを全く使わないこともあります。

通常、 `update()` や `saveOrUpdate()` は次のシナリオで使われます:

- アプリケーションが最初のセッションでオブジェクトをロードします。

- オブジェクトが UI 層に送られます。

- オブジェクトに対して変更が加えられます。

- オブジェクトがビジネスロジック層に送られます。

- アプリケーションは、2番目のセッションで `update()` を呼ぶことで、これらの変更を永続化します。

`saveOrUpdate()` は以下のことを行います:

- オブジェクトがこのセッションで、すでに永続化されていれば、何もしません。

- そのセッションに関連づいている別のオブジェクトが同じ識別子を持っているなら、例外を投げます。

- オブジェクトの識別子が値を持たないならば、 `save()` します。

- オブジェクトの識別子が値を持ち、その値が新たにインスタンス化されたオブジェクトのための値である場合、そのオブジェクトを `save()` します。

- オブジェクトが（ `<version>` や `<timestamp>` によって）バージョンづけされていて、バージョンのプロパティが値を持ち、その値が新しくインスタンス化されたオブジェクトのための値である場合、そのオブジェクトを `save()` します。

- そうでない場合は、そのオブジェクトを `update()` します。

そして、 `merge()` は以下のように非常に異なります:

- 同じ識別子を持つ永続化インスタンスがその時点でセッションと関連付いているならば、引数で受け取ったオブジェクトの状態を永続化インスタンスにコピーします。

- 永続化インスタンスがその時点でセッションに関連付いていないなら、データベースからそれをロードするか、あるいは、新しい永続化インスタンスを作成します。

- 永続化インスタンスが返されます。

- 引数として与えたインスタンスはセッションと関連を持ちません。それは、分離状態のままです。

## 11.8. 永続オブジェクトの削除

`Session.delete()` はオブジェクトの状態をデータベースから削除します。もちろん、削除したオブジェクトをアプリケーションが保持したままでもよいです。そのため、 `delete()` は永続インスタンスを transient にするものと考えるのが一番です。

    sess.delete(cat);

外部キー制約に違反するリスクもなく、好きな順番でオブジェクトを削除することができます。ただし、間違った順番でオブジェクトを削除すると、外部キーカラムの `NOT NULL` 制約に違反する可能性があります。例えば、親オブジェクトを削除したときに、子供オブジェクトを削除し忘れた場合です。

## 11.9. 異なる二つのデータストア間でのオブジェクトのレプリケーション

永続インスタンスのグラフを別のデータストアに永続化する場合に、識別子の値を再生成せずにすむと便利な場合があります。

    //retrieve a cat from one database

    Session session1 = factory1.openSession();

    Transaction tx1 = session1.beginTransaction();

    Cat cat = session1.get(Cat.class, catId);

    tx1.commit();

    session1.close();

    //reconcile with a second database

    Session session2 = factory2.openSession();

    Transaction tx2 = session2.beginTransaction();

    session2.replicate(cat, ReplicationMode.LATEST_VERSION);

    tx2.commit();

    session2.close();

レプリケーション先のデータベースに行が既にある場合、 `replicate()` が衝突をどのように扱うかを `ReplicationMode` で指定します。

- `ReplicationMode.IGNORE` - 同じ識別子を持つ行がデータベースに存在するなら、そのオブジェクトを無視します。

- `ReplicationMode.OVERWRITE` - 同じ識別子を持つ既存の行をすべて上書きします。

- `ReplicationMode.EXCEPTION` - 同じ識別子を持つ行がデータベースに存在するなら、例外を投げます。

- `ReplicationMode.LATEST_VERSION` - 行に保存されているバージョン番号が、引数のオブジェクトのバージョン番号より古いならば、その行を上書きします。

次のようなケースで、この機能を使用します。異なるデータベースインスタンスに入れられたデータの同期、製品更新時におけるシステム設定情報の更新、非 ACID トランザクションのなかで加えられた変更のロールバックなどです。

## 11.10. セッションのフラッシュ

JDBC コネクションの状態とメモリ上のオブジェクトの状態を同期させるために必要な SQL 文を `Session` が実行することがときどきあります。この処理 flush は、デフォルトでは次のときに起こります。

- クエリを実行する前

- `org.hibernate.Transaction.commit()` を実行したとき

- `Session.flush()` を実行したとき

SQL 文は以下の順番で発行されます。

1. すべてのエンティティの挿入。これは、 `Session.save()` を使ってセーブしたオブジェクトの順に実行していきます。

2. すべてのエンティティの更新

3. すべてのコレクションの削除

4. すべてのコレクションの要素に対する削除、更新、挿入

5. すべてのコレクションの挿入

6. すべてのエンティティの削除。これは、 `Session.delete()` を使って削除したオブジェクトの順に実行していきます。

(１つ例外があります。 `native` ID 生成を使ったオブジェクトは、それらがセーブされたときに挿入されます。）

明示的に `flush()` するときを除いて、 いつ `Session` が JDBC をコールするのかについて絶対的な保証はありません。ただし、それらが実行される 順番 だけは保証されます。また、 Hibernate は、 `Query.list(..)` が古いデータや間違ったデータ返さないことを保証しています。

It is possible to change the default behavior so that flush occurs less frequently. The `FlushMode` class defines three different modes: only flush at commit time when the Hibernate `Transaction` API is used, flush automatically using the explained routine, or never flush unless `flush()` is called explicitly. The last mode is useful for long running units of work, where a `Session` is kept open and disconnected for a long time (see 「拡張セッションと自動バージョニング」).

    sess = sf.openSession();

    Transaction tx = sess.beginTransaction();

    sess.setFlushMode(FlushMode.COMMIT); // allow queries to return stale state

    Cat izi = (Cat) sess.load(Cat.class, id);

    izi.setName(iznizi);

    // might return stale data

    sess.find("from Cat as cat left outer join cat.kittens kitten");

    // change to izi is not flushed!

    ...

    tx.commit(); // flush occurs

    sess.close();

During flush, an exception might occur (e.g. if a DML operation violates a constraint). Since handling exceptions involves some understanding of Hibernate's transactional behavior, we discuss it in 13章Transactions and Concurrency.

## 11.11. 連鎖的な永続化

個々のオブジェクトをセーブしたり、削除したり、再追加したりすることはかなり面倒です。特に、関連するオブジェクトを扱うような場合には際立ちます。よくあるのは、親子関係を扱うケースです。以下の例を考えてみましょう:

もし、親子関係の子が値型なら（例えば、住所や文字列のコレクション）、それらのライフサイクルは親に依存しており、便利な状態変化の「カスケード」を使うために、追加の作業は必要はありません。親がセーブされたとき、値型の子オブジェクトも同じようにセーブされますし、親が削除されたときは、子も削除されます。その他の操作も同じです。コレクションから1つの子を削除するような操作でもうまくいきます。すなわち、 Hibernate はこの削除操作を検出すると、値型のオブジェクトは参照を共有できないので、データベースからその子供を削除します。

ここで、親と子が値型でなくエンティティであるとして同じシナリオを考えてみましょう。（例えば、カテゴリーと品目の関係や親と子の猫の関係です。）エンティティは、それ自身がライフサイクルを持ち、参照の共有をサポートします。（そのため、コレクションからエンティティを削除することは、エンティティ自身の削除を意味しません。）また、エンティティは、デフォルトでは、関連する他のエンティティへ状態をカスケードすることはありません。 Hibernate は 到達可能性による永続化 をデフォルトでは実行しません。

Hibernate の Session の基本操作（ `persist(), merge(), saveOrUpdate(), delete(), lock(), refresh(), evict(), replicate()` が含まれます）に対して、それぞれに対応するカスケードスタイルがあります。それぞれのカスケードスタイルには、 `create, merge, save-update, delete, lock, refresh, evict, replicate` という名前がついています。もし、関連に沿ってカスケードさせたい操作があるなら、マッピングファイルにそう指定しなければなりません。例えば、以下のようにします:

    <one-to-one name="person" cascade="persist"/>

カスケードスタイルは、組み合わせることができます:

    <one-to-one name="person" cascade="persist,delete,lock"/>

すべての 操作を関連に沿ってカスケードするよう指定するときは、 `cascade="all"` を使います。デフォルトの `cascade="none"` は、どの操作もカスケードしないことを意味します。

In case you are using annotatons you probably have noticed the `cascade` attribute taking an array of `CascadeType` as a value. The cascade concept in JPA is very is similar to the transitive persistence and cascading of operations as described above, but with slightly different semantics and cascading types:

- `CascadeType.PERSIST`: cascades the persist (create) operation to associated entities persist() is called or if the entity is managed

- `CascadeType.MERGE`: cascades the merge operation to associated entities if merge() is called or if the entity is managed

- `CascadeType.REMOVE`: cascades the remove operation to associated entities if delete() is called

- `CascadeType.REFRESH:` cascades the refresh operation to associated entities if refresh() is called

- `CascadeType.DETACH:` cascades the detach operation to associated entities if detach() is called

- `CascadeType.ALL`: all of the above

## 注意

CascadeType.ALL also covers Hibernate specific operations like save-update, lock etc...

A special cascade style, `delete-orphan`, applies only to one-to-many associations, and indicates that the `delete()` operation should be applied to any child object that is removed from the association. Using annotations there is no `CascadeType.DELETE-ORPHAN` equivalent. Instead you can use the attribute `orphanRemoval as seen in` 例11.4「@OneToMany with orphanRemoval」. If an entity is removed from a `@OneToMany` collection or an associated entity is dereferenced from a `@OneToOne` association, this associated entity can be marked for deletion if `orphanRemoval` is set to true.

例11.4 `@OneToMany` with `orphanRemoval`

    @Entity

    public class Customer {

       private Set<Order> orders;

       @OneToMany(cascade=CascadeType.ALL, orphanRemoval=true)

       public Set<Order> getOrders() { return orders; }

       public void setOrders(Set<Order> orders) { this.orders = orders; }

       [...]

    }

    @Entity

    public class Order { ... }

    Customer customer = em.find(Customer.class, 1l);

    Order order = em.find(Order.class, 1l);

    customer.getOrders().remove(order); //order will be deleted by cascade

おすすめ：

- It does not usually make sense to enable cascade on a many-to-one or many-to-many association. In fact the `@ManyToOne` and `@ManyToMany` don't even offer a `orphanRemoval` attribute. Cascading is often useful for one-to-one and one-to-many associations.

- If the child object's lifespan is bounded by the lifespan of the parent object, make it a life cycle object by specifying `cascade="all,delete-orphan"(`@OneToMany(cascade=CascadeType.ALL, orphanRemoval=true)`)`.

- それ以外の場合は、カスケードはほとんど必要ないでしょう。しかし、同じトランザクションのなかで親と子が一緒に動作することが多いと思い、いくらかのコードを書く手間を省きたいのであれば、 `cascade="persist,merge,save-update"` を使うことを考えましょう。

`cascade="all"` でマッピングした関連（単値関連やコレクション）は、 親子 スタイルの関連とマークされます。それは、親のセーブ/更新/削除が、子のセーブ/更新/削除を引き起こす関係のことです。

Furthermore, a mere reference to a child from a persistent parent will result in save/update of the child. This metaphor is incomplete, however. A child which becomes unreferenced by its parent is not automatically deleted, except in the case of a one-to-many association mapped with `cascade="delete-orphan"`. The precise semantics of cascading operations for a parent/child relationship are as follows:

- 親が `persist()` に渡されたならば、すべての子は `persist()` に渡されます。

- `merge()` に渡されたならば、すべての子は `merge()` に渡されます。

- 親が `save()` 、 `update()` 、 `saveOrUpdate()` に渡されたならば、すべての子は `saveOrUpdate()` に渡されます。

- transient または detached の子が、永続化された親に参照されたならば、 `saveOrUpdate()` に渡されます。

- 親が削除されたならば、すべての子は、 `delete()` に渡されます。

- 子が永続化された親から参照されなくなったときは、 特に何も起こりません 。よって、アプリケーションが必要であれば、明示的に削除する必要があります。ただし、 `cascade="delete-orphan"` の場合を除きます。この場合、「親のない」子は削除されます。

最後に、操作のカスケードがオブジェクトグラフに適用されるのは、 コールした時 あるいは、 flushした時 であることに注意してください。すべての操作は、その操作が実行されたときに、到達可能な関連するエンティティに対してカスケードが可能ならカスケードします。しかし、 `save-upate` と `delete-orphan` は、 `Session` が flush している間に、すべての到達可能な関連するエンティティに伝播します。

## 11.12. メタデータの使用

Hibernate は、すべてのエンティティと値型の非常にリッチなメタレベルのモデルを必要とします。ときどき、このモデルはアプリケーションにとってとても役に立ちます。例えば、アプリケーションは、 Hibernate のメタデータを使って、「賢い」ディープコピーアルゴリズムを実装できるかもしません。そのアルゴリズムとは、どのオブジェクトがコピーされるべきか（例：可変の値型）やどのオブジェクトはコピーされないべきか（例：不変な値型や可能なら関連するエンティティ）を判断できるものです。

Hibernate は `ClassMetadata` と `CollectionMetadata` インタフェースと `Type` 階層を通してメタデータを公開します。メタデータインターフェースのインスタンスは、 `SessionFactory` から得られます。

    Cat fritz = ......;

    ClassMetadata catMeta = sessionfactory.getClassMetadata(Cat.class);

    Object[] propertyValues = catMeta.getPropertyValues(fritz);

    String[] propertyNames = catMeta.getPropertyNames();

    Type[] propertyTypes = catMeta.getPropertyTypes();

    // get a Map of all properties which are not collections or associations

    Map namedValues = new HashMap();

    for ( int i=0; i<propertyNames.length; i++ ) {

        if ( !propertyTypes[i].isEntityType() && !propertyTypes[i].isCollectionType() ) {

            namedValues.put( propertyNames[i], propertyValues[i] );

        }

    }

## 第12章 Read-only entities

## 重要項目

Hibernate's treatment of read-only entities may differ from what you may have encountered elsewhere. Incorrect usage may cause unexpected results.

When an entity is read-only:

- Hibernate does not dirty-check the entity's simple properties or single-ended associations;

- Hibernate will not update simple properties or updatable single-ended associations;

- Hibernate will not update the version of the read-only entity if only simple properties or single-ended updatable associations are changed;

In some ways, Hibernate treats read-only entities the same as entities that are not read-only:

- Hibernate cascades operations to associations as defined in the entity mapping.

- Hibernate updates the version if the entity has a collection with changes that dirties the entity;

- A read-only entity can be deleted.

Even if an entity is not read-only, its collection association can be affected if it contains a read-only entity.

For details about the affect of read-only entities on different property and association types, see 「Read-only affect on property type」.

For details about how to make entities read-only, see 「Making persistent entities read-only」

Hibernate does some optimizing for read-only entities:

- It saves execution time by not dirty-checking simple properties or single-ended associations.

- It saves memory by deleting database snapshots.

## 12.1. Making persistent entities read-only

Only persistent entities can be made read-only. Transient and detached entities must be put in persistent state before they can be made read-only.

Hibernate provides the following ways to make persistent entities read-only:

- you can map an entity class as immutable; when an entity of an immutable class is made persistent, Hibernate automatically makes it read-only. see 「Entities of immutable classes」 for details

- you can change a default so that entities loaded into the session by Hibernate are automatically made read-only; see 「Loading persistent entities as read-only」 for details

- you can make an HQL query or criteria read-only so that entities loaded when the query or criteria executes, scrolls, or iterates, are automatically made read-only; see 「Loading read-only entities from an HQL query/criteria」 for details

- you can make a persistent entity that is already in the in the session read-only; see 「Making a persistent entity read-only」 for details

### 12.1.1. Entities of immutable classes

When an entity instance of an immutable class is made persistent, Hibernate automatically makes it read-only.

An entity of an immutable class can created and deleted the same as an entity of a mutable class.

Hibernate treats a persistent entity of an immutable class the same way as a read-only persistent entity of a mutable class. The only exception is that Hibernate will not allow an entity of an immutable class to be changed so it is not read-only.

### 12.1.2. Loading persistent entities as read-only

## 注意

Entities of immutable classes are automatically loaded as read-only.

To change the default behavior so Hibernate loads entity instances of mutable classes into the session and automatically makes them read-only, call:

    Session.setDefaultReadOnly( true );

To change the default back so entities loaded by Hibernate are not made read-only, call:

    Session.setDefaultReadOnly( false );

You can determine the current setting by calling:

    Session.isDefaultReadOnly();

If Session.isDefaultReadOnly() returns true, entities loaded by the following are automatically made read-only:

- Session.load()

- Session.get()

- Session.merge()

- executing, scrolling, or iterating HQL queries and criteria; to override this setting for a particular HQL query or criteria see 「Loading read-only entities from an HQL query/criteria」

Changing this default has no effect on:

- persistent entities already in the session when the default was changed

- persistent entities that are refreshed via Session.refresh(); a refreshed persistent entity will only be read-only if it was read-only before refreshing

- persistent entities added by the application via Session.persist(), Session.save(), and Session.update() Session.saveOrUpdate()

### 12.1.3. Loading read-only entities from an HQL query/criteria

## 注意

Entities of immutable classes are automatically loaded as read-only.

If Session.isDefaultReadOnly() returns false (the default) when an HQL query or criteria executes, then entities and proxies of mutable classes loaded by the query will not be read-only.

You can override this behavior so that entities and proxies loaded by an HQL query or criteria are automatically made read-only.

For an HQL query, call:

    Query.setReadOnly( true );

`Query.setReadOnly( true )` must be called before `Query.list()`, `Query.uniqueResult()`, `Query.scroll()`, or `Query.iterate()`

For an HQL criteria, call:

    Criteria.setReadOnly( true );

`Criteria.setReadOnly( true )` must be called before `Criteria.list()`, `Criteria.uniqueResult()`, or `Criteria.scroll()`

Entities and proxies that exist in the session before being returned by an HQL query or criteria are not affected.

Uninitialized persistent collections returned by the query are not affected. Later, when the collection is initialized, entities loaded into the session will be read-only if Session.isDefaultReadOnly() returns true.

Using `Query.setReadOnly( true )` or `Criteria.setReadOnly( true )` works well when a single HQL query or criteria loads all the entities and intializes all the proxies and collections that the application needs to be read-only.

When it is not possible to load and initialize all necessary entities in a single query or criteria, you can temporarily change the session default to load entities as read-only before the query is executed. Then you can explicitly initialize proxies and collections before restoring the session default.

    Session session = factory.openSession();
    Transaction tx = session.beginTransaction();

    setDefaultReadOnly( true );
    Contract contract =
       ( Contract ) session.createQuery(
               "from Contract where customerName = 'Sherman'" )
               .uniqueResult();
    Hibernate.initialize( contract.getPlan() );
    Hibernate.initialize( contract.getVariations() );
    Hibernate.initialize( contract.getNotes() );
    setDefaultReadOnly( false );
    ...
    tx.commit();
    session.close();

If Session.isDefaultReadOnly() returns true, then you can use Query.setReadOnly( false ) and Criteria.setReadOnly( false ) to override this session setting and load entities that are not read-only.

### 12.1.4. Making a persistent entity read-only

## 注意

Persistent entities of immutable classes are automatically made read-only.

To make a persistent entity or proxy read-only, call:

    Session.setReadOnly(entityOrProxy, true)

To change a read-only entity or proxy of a mutable class so it is no longer read-only, call:

    Session.setReadOnly(entityOrProxy, false)

## 重要項目

When a read-only entity or proxy is changed so it is no longer read-only, Hibernate assumes that the current state of the read-only entity is consistent with its database representation. If this is not true, then any non-flushed changes made before or while the entity was read-only, will be ignored.

To throw away non-flushed changes and make the persistent entity consistent with its database representation, call:

    session.refresh( entity );

To flush changes made before or while the entity was read-only and make the database representation consistent with the current state of the persistent entity:

    // evict the read-only entity so it is detached
    session.evict( entity );

    // make the detached entity (with the non-flushed changes) persistent
    session.update( entity );

    // now entity is no longer read-only and its changes can be flushed
    s.flush();

## 12.2. Read-only affect on property type

The following table summarizes how different property types are affected by making an entity read-only.

表12.1 Affect of read-only entity on property types

Property/Association Type | Changes flushed to DB?
--- | ---
Simple (「Simple properties」) | no*
Unidirectional one-to-one Unidirectional many-to-one (「Unidirectional one-to-one and many-to-one」) | no* no*
Unidirectional one-to-many Unidirectional many-to-many (「Unidirectional one-to-many and many-to-many」) | yes yes
Bidirectional one-to-one (「Bidirectional one-to-one」) | only if the owning entity is not read-only*
Bidirectional one-to-many/many-to-one inverse collection non-inverse collection (「Bidirectional one-to-many/many-to-one」) | only added/removed entities that are not read-only* yes
Bidirectional many-to-many (「Bidirectional many-to-many」) | yes

* Behavior is different when the entity having the property/association is read-only, compared to when it is not read-only.

### 12.2.1. Simple properties

When a persistent object is read-only, Hibernate does not dirty-check simple properties.

Hibernate will not synchronize simple property state changes to the database. If you have automatic versioning, Hibernate will not increment the version if any simple properties change.

    Session session = factory.openSession();
    Transaction tx = session.beginTransaction();

    // get a contract and make it read-only
    Contract contract = ( Contract ) session.get( Contract.class, contractId );
    session.setReadOnly( contract, true );

    // contract.getCustomerName() is "Sherman"
    contract.setCustomerName( "Yogi" );
    tx.commit();

    tx = session.beginTransaction();

    contract = ( Contract ) session.get( Contract.class, contractId );
    // contract.getCustomerName() is still "Sherman"
    ...
    tx.commit();
    session.close();

### 12.2.2. Unidirectional associations

#### 12.2.2.1. Unidirectional one-to-one and many-to-one

Hibernate treats unidirectional one-to-one and many-to-one associations in the same way when the owning entity is read-only.

We use the term unidirectional single-ended association when referring to functionality that is common to unidirectional one-to-one and many-to-one associations.

Hibernate does not dirty-check unidirectional single-ended associations when the owning entity is read-only.

If you change a read-only entity's reference to a unidirectional single-ended association to null, or to refer to a different entity, that change will not be flushed to the database.

## 注意

If an entity is of an immutable class, then its references to unidirectional single-ended associations must be assigned when that entity is first created. Because the entity is automatically made read-only, these references can not be updated.

If automatic versioning is used, Hibernate will not increment the version due to local changes to unidirectional single-ended associations.

In the following examples, Contract has a unidirectional many-to-one association with Plan. Contract cascades save and update operations to the association.

The following shows that changing a read-only entity's many-to-one association reference to null has no effect on the entity's database representation.

    // get a contract with an existing plan;
    // make the contract read-only and set its plan to null
    tx = session.beginTransaction();
    Contract contract = ( Contract ) session.get( Contract.class, contractId );
    session.setReadOnly( contract, true );
    contract.setPlan( null );
    tx.commit();

    // get the same contract
    tx = session.beginTransaction();
    contract = ( Contract ) session.get( Contract.class, contractId );

    // contract.getPlan() still refers to the original plan;

    tx.commit();
    session.close();

The following shows that, even though an update to a read-only entity's many-to-one association has no affect on the entity's database representation, flush still cascades the save-update operation to the locally changed association.

    // get a contract with an existing plan;
    // make the contract read-only and change to a new plan
    tx = session.beginTransaction();
    Contract contract = ( Contract ) session.get( Contract.class, contractId );
    session.setReadOnly( contract, true );
    Plan newPlan = new Plan( "new plan"
    contract.setPlan( newPlan);
    tx.commit();

    // get the same contract
    tx = session.beginTransaction();
    contract = ( Contract ) session.get( Contract.class, contractId );
    newPlan = ( Contract ) session.get( Plan.class, newPlan.getId() );

    // contract.getPlan() still refers to the original plan;
    // newPlan is non-null because it was persisted when
    // the previous transaction was committed;

    tx.commit();
    session.close();

#### 12.2.2.2. Unidirectional one-to-many and many-to-many

Hibernate treats unidirectional one-to-many and many-to-many associations owned by a read-only entity the same as when owned by an entity that is not read-only.

Hibernate dirty-checks unidirectional one-to-many and many-to-many associations;

The collection can contain entities that are read-only, as well as entities that are not read-only.

Entities can be added and removed from the collection; changes are flushed to the database.

If automatic versioning is used, Hibernate will update the version due to changes in the collection if they dirty the owning entity.

### 12.2.3. Bidirectional associations

#### 12.2.3.1. Bidirectional one-to-one

If a read-only entity owns a bidirectional one-to-one association:

- Hibernate does not dirty-check the association.

- updates that change the association reference to null or to refer to a different entity will not be flushed to the database.

- If automatic versioning is used, Hibernate will not increment the version due to local changes to the association.

## 注意

If an entity is of an immutable class, and it owns a bidirectional one-to-one association, then its reference must be assigned when that entity is first created. Because the entity is automatically made read-only, these references cannot be updated.

When the owner is not read-only, Hibernate treats an association with a read-only entity the same as when the association is with an entity that is not read-only.

#### 12.2.3.2. Bidirectional one-to-many/many-to-one

A read-only entity has no impact on a bidirectional one-to-many/many-to-one association if:

- the read-only entity is on the one-to-many side using an inverse collection;

- the read-only entity is on the one-to-many side using a non-inverse collection;

- the one-to-many side uses a non-inverse collection that contains the read-only entity

When the one-to-many side uses an inverse collection:

- a read-only entity can only be added to the collection when it is created;

- a read-only entity can only be removed from the collection by an orphan delete or by explicitly deleting the entity.

#### 12.2.3.3. Bidirectional many-to-many

Hibernate treats bidirectional many-to-many associations owned by a read-only entity the same as when owned by an entity that is not read-only.

Hibernate dirty-checks bidirectional many-to-many associations.

The collection on either side of the association can contain entities that are read-only, as well as entities that are not read-only.

Entities are added and removed from both sides of the collection; changes are flushed to the database.

If automatic versioning is used, Hibernate will update the version due to changes in both sides of the collection if they dirty the entity owning the respective collections.

## 第13章 Transactions and Concurrency

Hibernate と同時実行制御について最も重要な点は、容易に理解できることです。 Hibernate は新たなロックの振る舞いを追加しておらず、直接 JDBC コネクションと JTA リソースを使用します。 JDBC 、 ANSI 、およびデータベース管理システム（DBMS）のトランザクション分離の仕様を少し時間をかけて勉強することを強く推奨します。

Hibernate はメモリ内のオブジェクトをロックしません。アプリケーションは、データベーストランザクションの分離レベルで定義した振る舞いを期待できます。トランザクションスコープのキャッシュでもある `Session` のお陰で、識別子やクエリにより検索したエンティティはリピータブルリードになります（スカラー値を返すようなレポートクエリは違います）。

バージョニングによる自動的な楽観的同時実行制御に加えて、 `SELECT FOR UPDATE` 文を使用して、行を悲観的ロックするための（マイナーな） API も提供します。楽観的同時実行制御とこの API については、この章の後のほうで議論します。

データベーストランザクションや長い対話（conversation、ロングトランザクション）だけでなく、 `Configuration`、`SessionFactory`、および `Session` という粒度で Hibernate が行う同時実行制御の議論を始めます。

## 13.1. session スコープと transaction スコープ

`SessionFactory` は生成することが高価で、スレッドセーフなオブジェクトです。よって、アプリケーションのすべてのスレッドで共有すべきです。通常、アプリケーションの起動時に、 `Configuration` インスタンスから１度だけ生成します。

`Session` は高価ではなく、スレッドセーフなオブジェクトでもありません。よって、１つの要求や１つの対話、１つの作業単位（unit of work）に対して１度だけ使い、その後で捨てるべきです。 `Session` は必要になるまで、 JDBC `Connection`（もしくは `DataSource`）を獲得しません。ゆえに、実際に使用するときまでリソースを消費しません。

この状況を完了させるために、データベーストランザクションについても考えなければなりません。データベース内のロックの競合を少なくするために、データベーストランザクションは可能な限り短くするべきです。長いデータベーストランザクションは、アプリケーションの高い並列実行性を阻害します。ゆえに、ユーザーが考えている間（作業単位が完了するまで）データベーストランザクションを開いたままにするのは、たいていの場合よい設計とはいえません。

作業単位というスコープとは何でしょうか？１つの Hibernate `Session` は、いくつかのデータベーストランザクションをまたがることができるでしょうか？または、スコープと一対一の関係でしょうか？いつ `Session` を開き、閉じるべきでしょうか？そして、データベーストランザクション境界をどのように分けるのでしょうか？

### 13.1.1. 作業単位（Unit of work）

First, let's define a unit of work. A unit of work is a design pattern described by Martin Fowler as 「 [maintaining] a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems. 」[PoEAA] In other words, its a series of operations we wish to carry out against the database together. Basically, it is a transaction, though fulfilling a unit of work will often span multiple physical database transactions (see 「長い対話」). So really we are talking about a more abstract notion of a transaction. The term "business transaction" is also sometimes used in lieu of unit of work.

１つ目は、 session-per-operation アンチパターンを使ってはいけません。すなわち、１つのスレッドの中で、単純なデータベース呼び出しの度に `Session` を開いて、閉じてはいけません。もちろん、データベーストランザクションについても同様です。アプリケーション中のデータベース呼び出しは、計画されたシーケンス（planned sequence）を使い、アトミックな作業単位に分類されます。（１つの SQL 文ごとにコミットする自動コミットが、使われないという意味でもあることに注意してください。自動コミットは、 SQL コンソールでアドホックな作業をする際に使うものです。 Hibernate は直ちに自動コミットモードを無効にします。もしくは、アプリケーションサーバーが無効化することを期待します。）データベーストランザクションはオプションではありません。データベースとのすべての通信は、データの読み込みであっても、書き込みであっても、トランザクションの中で行わなければなりません。説明すると、データ読み込みに対して、自動コミットは避けるべきです。なぜなら、多数の小さなトランザクションは、明確に定義された１つの作業単位と比べて、パフォーマンスがよくなることはありません。後者は保守性や拡張性もよりすぐれています。

マルチユーザーのクライアント／サーバーアプリケーションの中で、最もよく使われるパターンは、 session-per-request です。このモデルの中では、クライアントから（ Hibernate 永続化層が動作する）サーバーへリクエストが送られ、新しい Hibernate `Session` が開かれます。そして、この作業単位の中ですべてのデータベース処理が実行されます。作業が完了した（そして、クライアントへのレスポンスが準備できた）時点で、 session をフラッシュし、閉じます。クライアントの要求を処理するために、１つのデータベーストランザクションを使用するでしょう。 `Session` を開き、閉じる際に、データベーストランザクションを開始し、コミットします。二つの関係は一対一です。このモデルは多くのアプリケーションに完全に適合します。

以降の実装にチャレンジしてください。 Hibernate は単純なこのパターンのために、予め組み込まれた "current session" の管理を提供します。サーバーリクエストを処理する際はトランザクションを開始しなければなりません。そして、レスポンスをクライアントに送信する前にトランザクションを終わらせます。好きな方法で実現できます。一般的な解決策は `ServletFilter` やサービスメソッドをポイントカットして AOP インターセプター、 proxy/interception コンテナです。 EJB コンテナは EJB セッション Bean をトランザクション境界としてアスペクトをクロスカットする実装の標準的な方法です（ CMT による宣言的）。プログラムによるトランザクション境界を使うと決めた場合、簡単に使うため、互換性のあるコードにするために、この章の後のほうにある Hibernate `Transaction` API のほうがよいです。

Your application code can access a "current session" to process the request by calling `sessionFactory.getCurrentSession()`. You will always get a `Session` scoped to the current database transaction. This has to be configured for either resource-local or JTA environments, see 「コンテキスト上のセッション」.

ときどき、「ビューを描画する」まで `セッション` とデータベーストランザクションのスコープを拡張すると便利なことがあります。これは、要求の処理と描画のフェーズを分けているサーブレットアプリケーションにおいて特に役立ちます。独自のインターセプタを実装すれば、ビューを描画するまでデータベーストランザクションを拡張するのは簡単です。しかし、コンテナ管理トランザクションの EJB に頼る場合は、簡単にはできません。なぜなら、ビューの描画を開始する前に、 EJB のメソッドがリターンした際に、トランザクションが完了するためです。この Open Session in View パターンに関連するヒントと例については、 Hibernate の Web サイトやフォーラムを参照してください。

### 13.1.2. 長い対話

session-per-request パターンは、作業単位を設計する際に役立つ考えというだけではありません。多くのビジネスプロセスは、ユーザーとの一連の相互作用全体を要求します。その相互作用には、データベースアクセスが含まれます。 Web とエンタープライズアプリケーションでは、データベーストランザクションがユーザーとの相互作用にまで渡ることは許されません。次の例をよく考えてみてください:

- ダイアログの最初の画面が開き、個々の `Session` とデータベーストランザクションの中でロードされたデータをユーザーに見せます。ユーザーはオブジェクトを自由に修正できます。

- 5分後にユーザーは "Save" をクリックし、修正が永続化されるのを期待します。また、この情報を編集したのは自分１人だけで、修正のコンフリクトは発生しないと期待します。

この作業単位を（ユーザーの視点で）長期の 対話 （もしくは、アプリケーショントランザクション ）と呼びます。アプリケーションにこれを実装する方法はたくさんあります。

最初に思いつく実装は、ユーザーが考えている間、 `Session` とデータベーストランザクションを開いたままにしておくことです。同時に修正されず、分離と原子性が保証されるように、データベース内のロックは保持したままにします。もちろん、これはアンチパターンです。なぜなら、ロックの競合が発生すると、アプリケーションが同時ユーザー数に応じてスケールアップできなくなるからです。

明らかに、対話を実装するためには、いくつかのデータベーストランザクションを使用するべきです。この場合、ビジネスプロセスの分離を維持することは、アプリケーション層の責務の１つになります。１つの対話は、通常いくつかのデータベーストランザクションに及びます。データベーストランザクションの１つのみ（最後の１つ）が更新したデータを保存し、他はデータを読むだけであれば、それはアトミックです（例えば、いくつかの要求／応答を繰り返すウィザード形式のダイアログ）。これは聞くより、実装したほうが簡単です。 Hibernate の機能を使うのであれば、特に簡単です:

- 自動バージョニング - Hibernate は自動的に楽観的同時実行制御ができます。ユーザーが考えている間に同時に修正がおきた場合、自動的に検出できます。通常、対話の終了時にチェックするだけです。

- 分離（Detached）オブジェクト - すでに議論した session-per-request パターンを使うと決定した場合、ロードされたすべてのインスタンスは、ユーザーが考えている間は、セッションから分離された状態になります。オブジェクトをセッションに再追加し、修正を永続化できます。これを session-per-request-with-detached-objects パターンと呼びます。自動バージョニングを使うことで、同時に行われる修正を分離できます。

- 拡張（もしくは、長い）セッション - Hibernate の `Session` は、データベーストランザクションをコミットした後、裏で結びついている JDBC コネクションを切断できます。そして、クライアントからの新しい要求が発生した際に、再接続できます。このパターンは、 session-per-conversation という名で知られており、オブジェクトをセッションへ再追加することさえ不要にします。自動バージョニングを使うことで、同時に行われる修正を分離できます。通常 `Session` を自動的にフラッシュさせず、明示的にフラッシュします。

session-per-request-with-detached-objects と session-per-conversation の２つは、利点と欠点を持っています。これについては、この章の後のほうで、楽観的同時実行制御の文脈の中で議論します。

### 13.1.3. オブジェクト識別子を考える

アプリケーションは、２つの異なる `Session` から同じ永続状態に同時にアクセスできます。しかし、２つの `Session` インスタンスが永続性クラスの１つのインスタンスを共有することはできません。ゆえに、識別子には２つの異なる概念があるということになります。

データベース識別子

  `foo.getId().equals( bar.getId() )`

JVM 識別子

  `foo==bar`

特定の `Session` に追加されたオブジェクトにとって （すなわち、１つの `Session` のスコープの中では） 、２つの概念は同じです。データベース同一性と JVM 同一性が一致することを、 Hibernate が保証します。しかし、アプリケーションが２つの異なるセッションから「同じ」（永続性識別子の）ビジネスオブジェクトに同時にアクセスする限り、２つのインスタンスは実際に（ JVM 識別子が）「異なり」ます。楽観的アプローチによって、 （自動バージョニングの） フラッシュ／コミット時にコンフリクトが解決されます。

このアプローチでは、 Hibernate とデータベースに同時実行についての心配が残ります。一方で、最高のスケーラビリティが提供されます。なぜなら、１スレッドの作業単位の中で一意性が保証されれば、高価なロックや同期化が不要になるためです。 `Session` ごとに１つのスレッドを貼り付ける限り、アプリケーションはビジネスオブジェクトを synchronize する必要はありません。 `Session` 内では、アプリケーションはオブジェクトを比較するために、 `==` を安全に使用できます。

けれども、 `Session` の外で `==` を使うアプリケーションは、予期しない結果に遭遇します。これは予期しない場所で起こりえます。例えば、２つの分離インスタンスを同じ `Set` に put したときなどです。両方とも同じデータベース識別子を持ちます（すなわち、同じ行を表します）。しかし、分離状態のインスタンスの JVM 識別子は当然保証されません。開発者は、永続性クラスの `equals()` と `hashCode()` メソッドをオーバーライドし、オブジェクト等価性の概念を実装すべきです。警告が１つあります。等価性の実装にデータベース識別子を使わないでください。ユニークな（普通は不変の）属性の組み合わせであるビジネスキーを使ってください。もし、一時オブジェクトが永続化された場合、データベース識別子が変わります。一時オブジェクトを（通常分離インスタンスと共に） `Set` に保持する場合、ハッシュコードが変わるということは、 `Set` の契約を破るということです。ビジネスキーのための属性は、データベースの主キーほど安定すべきではないです。オブジェクトが同じ `Set` の中にいる間だけ、安定を保証すべきです。この問題のより徹底的な議論は、 Hibernate の Web サイトを参照してください。また、これは Hibernate の問題ではなく、単に Java オブジェクトの識別子や等価性をどのように実装すべきかということです。

### 13.1.4. 一般的な問題

session-per-user-session と session-per-application アンチパターンは使ってはいけません（もちろん、まれに例外があります）。注記：下記の問題のいくつかは、推奨されるパターンとしても出現します。設計を決定する前に、裏の意味を理解するようにしてください。

- `Session` はスレッドセーフではありません。 HTTP リクエスト、セッション Bean 、 Swing ワーカーのように、同時実行が可能なものが `Session` インスタンスを共有すると、競合状態を引き起こします。（後で議論する） `HttpSession` の中で Hibernate `Session` を保持する場合、 HttpSession へのアクセスを同期化することを考慮すべきです。さもなければ、ユーザーが十分早くリロードをクリックすると、同時に走る２つのスレッドの中で、同じ `Session` が使われます。

- Hibernate が例外を投げた場合は、データベーストランザクションをロールバックし、直ちに `Session` を閉じるべきです （詳細を後で議論します） 。 `Session` がアプリケーションに結び付けられているのであれば、アプリケーションを停止すべきです。データベーストランザクションをロールバックしても、ビジネスオブジェクトはトランザクションを開始したときの状態に戻りません。これは、データベースの状態とビジネスオブジェクトは同期していないことを意味します。通常これは問題になりません。なぜなら、例外は回復できないからです。とにかくロールバックした後にやり直すべきです。

- The `Session` caches every object that is in a persistent state (watched and checked for dirty state by Hibernate). If you keep it open for a long time or simply load too much data, it will grow endlessly until you get an OutOfMemoryException. One solution is to call `clear()` and `evict()` to manage the `Session` cache, but you should consider a Stored Procedure if you need mass data operations. Some solutions are shown in 15章バッチ処理. Keeping a `Session` open for the duration of a user session also means a higher probability of stale data.

## 13.2. データベーストランザクション境界

データベース （もしくはシステム） トランザクションの境界は、常に必要です。データベーストランザクションの外で、データベースとの通信は起きません （これは自動コミットモードに慣れている多くの開発者を混乱させるかもしれません） 。読み込むだけの操作にでも、いつも明確なトランザクション境界を使用してください。分離レベルとデータベースの能力次第で、これは必要ないかもしれませんが、常にトランザクション境界を明示的に指定しても、マイナス面は全くありません。確かに、１つのデータベーストランザクションは多数の小さなトランザクションより （データの読み込みであっても） パフォーマンスがすぐれています。

J2EE 環境に管理されていない状態 （すなわち、スタンドアロン、単純な Web や Swing アプリケーション）でも、管理された状態でも、 Hibernate アプリケーションを実行できます。管理されていない環境では、 Hiberante がデータベースのコネクションプールを提供します。アプリケーション開発者は、トランザクション境界を手動で設定しなければなりません。言い換えると、データベーストランザクションの開始、コミット、ロールバックを開発者自身が設定する必要があるということです。通常、管理された環境では、コンテナ管理によるトランザクション （CMT） が提供されます。例えば、セッション Bean のデプロイメントディスクリプタで宣言的に定義し、トランザクションを組み立てます。プログラムによるトランザクション境界はもう必要ありません。

しかしながら、管理されていないリソースローカルな環境と JTA に依存したシステム （CMT ではなく BMT） の両方に、永続化層をポータブルに保つのは、しばしば望ましいことです。デプロイ環境のネイティブのトランザクションシステムを呼び出す `Transaction` というラッパー API を Hibernate が提供します。この API を使うかは任意ですが、 CMT のセッション Bean を使わないのであれば、使うことを強く推奨します。

通常、 `Session` 終了は、４つの異なるフェーズを含みます:

- セッションのフラッシュ

- トランザクションのコミット

- セッションのクローズ

- 例外のハンドリング

セッションのフラッシュについては、前の方で既に議論しました。管理された環境と管理されていない環境の両方について、トランザクション境界と例外ハンドリングをもっと詳しく見ていきましょう。

### 13.2.1. 管理されていない環境

Hibernate 永続化層を管理されていない環境で実装する場合は、通常単純なコネクションプール （すなわち DataSource ではない） によって、データベースコネクションを制御します。 Hibernate はそのコネクションプールから必要なコネクションを取得します。セッション／トランザクション制御のイディオムは次のようになります：

    // Non-managed environment idiom

    Session sess = factory.openSession();

    Transaction tx = null;

    try {

        tx = sess.beginTransaction();

        // do some work

        ...

        tx.commit();

    }

    catch (RuntimeException e) {

        if (tx != null) tx.rollback();

        throw e; // or display error message

    }

    finally {

        sess.close();

    }

You do not have to `flush()` the `Session` explicitly: the call to `commit()` automatically triggers the synchronization depending on the FlushMode for the session. A call to `close()` marks the end of a session. The main implication of `close()` is that the JDBC connection will be relinquished by the session. This Java code is portable and runs in both non-managed and JTA environments.

より適応性のある解決策は、 Hibernate に予め組み込まれている "current session" コンテキスト管理です。言葉で説明するより下記を見たほうが速いでしょう。

    // Non-managed environment idiom with getCurrentSession()

    try {

        factory.getCurrentSession().beginTransaction();

        // do some work

        ...

        factory.getCurrentSession().getTransaction().commit();

    }

    catch (RuntimeException e) {

        factory.getCurrentSession().getTransaction().rollback();

        throw e; // or display error message

    }

正規のアプリケーションの中では、このようなコードの切れ端を決して見ないでしょう。致命的な （システム） 例外は、常に「最上位」でキャッチすべきです。言い換えれば、 （永続化層で） Hibernate 呼び出しを実行するコードと、 `RuntimeException` を制御する （通常はクリーンアップと終了のみ行うことができる） コードは、別々の層の中にあります。 Hibernate によるカレントコンテキスト管理は、この設計をかなり単純にします。必要なのは、 `SessionFactory` にアクセスすることだけです。例外処理は、この章の後のほうで議論します。

注記：（デフォルトですが） `org.hibernate.transaction.JDBCTransactionFactory` を選択するべきです。第2の用例としては、 `hibernate.current_session_context_class` を `"thread"` とするとよいでしょう。

### 13.2.2. JTA を使用する

永続化層をアプリケーションサーバー （例えば、 EJB セッション Bean の背後） で実行する場合、 Hibernate から取得するすべてのデータソースコネクションは、自動的にグローバル JTA トランザクションの一部になります。 EJB を使わずに、スタンドアロンの JTA 実装を導入することもできます。 JTA 統合のために、 Hibernate は２つの戦略を提供します。

Bean 管理トランザクション（BMT）を使い、 `Transaction` API を使う場合、 Hibernate はアプリケーションサーバーに BMT トランザクションの開始と終わりを告げます。すなわち、トランザクション管理のコードは、管理されない環境と同じになります。

    // BMT idiom

    Session sess = factory.openSession();

    Transaction tx = null;

    try {

        tx = sess.beginTransaction();

        // do some work

        ...

        tx.commit();

    }

    catch (RuntimeException e) {

        if (tx != null) tx.rollback();

        throw e; // or display error message

    }

    finally {

        sess.close();

    }

トランザクション境界として `Session` を使いたい場合、簡単にコンテキストを伝播する機能である `getCurrentSession()` があるので、 JTAの `UserTransaction` API を直接使用すべきでしょう。

    // BMT idiom with getCurrentSession()

    try {

        UserTransaction tx = (UserTransaction)new InitialContext()

                                .lookup("java:comp/UserTransaction");

        tx.begin();

        // Do some work on Session bound to transaction

        factory.getCurrentSession().load(...);

        factory.getCurrentSession().persist(...);

        tx.commit();

    }

    catch (RuntimeException e) {

        tx.rollback();

        throw e; // or display error message

    }

CMT では、トランザクション境界をセッション Bean のデプロイメントディスクリプタで定義し、プログラムでは行いません。ゆえに、コードは次のように少なくなります:

    // CMT idiom

     Session sess = factory.getCurrentSession();

     // do some work

     ...

CMT/EJB の中では、常にロールバックが自動的に実施されます。なぜなら、セッション Bean のメソッドにより投げられた制御されていない `RuntimeException` は、グローバルトランザクションをロールバックするようにコンテナに伝えるためです。 これは、 BMT もしくは CMT と一緒に Hibernate `Transaction` API を使う必要はまったくないということを意味し、トランザクションにバインドする「現在の」セッションを自動伝搬できます。

Hibernate のトランザクションファクトリを設定する際に、 JTA を直接使う （BMTの） 場合は `org.hibernate.transaction.JTATransactionFactory` を、 CMT セッション Bean の中では `org.hibernate.transaction.CMTTransactionFactory` を選択すべきだということに注意してください。 `hibernate.transaction.manager_lookup_class` をセットすることも思い出してください。なお、 `hibernate.current_session_context_class` は、セットしないか（後方互換）、 `"jta"` をセットしてください。

`getCurrentSession()` オペレーションは、 JTA 環境では１つの欠点を持ちます。デフォルトで使われる `after_statement` コネクションリリースモードを使用する上で、警告が１つあります。 JTA 仕様の愚かな制約のために、 `scroll()` または `iterate()` が返した、閉じられていない `ScrollableResults` または `Iterator` インスタンスを Hibernate が自動的にクリーンアップすることはできません。 `finally` ブロックの中で、 `ScrollableResults.close()` または `Hibernate.close(Iterator)` を明示的に呼び出して、裏に潜んだデータベースカーソルを解放 しなければなりません。 （もちろん、多くのアプリケーションでは、 JTA か CMT コードで `scroll()` や `iterate()` の使用を避けるのは容易です。）

### 13.2.3. 例外ハンドリング

`Session` が例外 （`SQLException`を含む） を投げた場合、直ちに、データベーストランザクションをロールバックし、 `Session.close()` を呼び、 `Session` インスタンスを破棄すべきです。 `Session` のいくつかのメソッドは、セッションの状態を 矛盾したまま にします。 Hibernate が投げた例外を、回復できるものとして扱うことはできません。 `finally` ブロックの中で `close()` を呼んで、 `Session` を確実に閉じてください。

`HibernateException` は、 Hibernate 永続化層の中で発生する多くのエラーをラップする、検査されない例外です （ Hibernate の古いバージョンは違いました） 。私たちの意見は、アプリケーション開発者に回復不可能な例外を下層でキャッチすることを強要すべきではないということです。多くのシステムでは、検査されない例外と致命的な例外は、コールスタックの最初のフレームの１つ （例えば、最上位の層で） でハンドリングし、エラーメッセージをアプリケーションユーザーに表示します （もしくは、他の適切な処理を実施します） 。 Hibernate は、`HibernateException` 以外の検査されない例外も投げることに注意してください。これらもまた、回復不可能であり、適切な処理を実施すべきです。

Hibernate は、データベースとの対話中に投げられた `SQLException` を `JDBCException` でラップします。実は、例外をより意味のある `JDBCException` のサブクラスに変換しようと試みます。元の `SQLException` は、 `JDBCException.getCause()` によりいつでも得られます。 Hibernate は、 `SessionFactory` に追加されている `SQLExceptionConverter` を使い、 `SQLException` を適当な `JDBCException` サブクラスに変換します。デフォルトでは、 `SQLExceptionConverter` は設定されている SQL 方言により定義されます。一方で、独自の実装に差し替えることもできます （詳細は、 `SQLExceptionConverterFactory` クラスの Javadoc を参照してください）。標準的な `JDBCException` のサブタイプを下記に示します。

- `JDBCConnectionException` - 基礎となる JDBC 通信のエラーを表します。

- `SQLGrammarException` - 発行する SQL の文法もしくは構文の問題を表します。

- `ConstraintViolationException` - 何らかの形式の完全性制約違反を表します。

- `LockAcquisitionException` - 要求された操作を実施するのに必要なロックレベルを得る際のエラーを表します。

- `GenericJDBCException` - 他のカテゴリに一致しなかった一般的な例外です。

### 13.2.4. トランザクションのタイムアウト

EJB のような管理された環境が提供するきわめて重要な特徴の１つは、トランザクションのタイムアウトです。これは管理されていないコードには提供できません。トランザクションタイムアウトは、不品行なトランザクションがユーザーにレスポンスを返さないまま、無期限にリソースを使い続けないことを保障します。管理された環境 （JTA） の外では、 Hibernate はこの機能をフルに提供できません。しかしながら、 Hibernate は次のようなデータアクセス操作の制御くらいはできます。データベースレベルのデッドロックや大きなリザルトセットを返すクエリを定義されたタイムアウトによって確実に制限します。管理された環境では、 Hibernate はトランザクションタイムアウトを JTA に委譲します。この機能は、 Hibernate の `Transaction` オブジェクトによって抽象化されています。

    Session sess = factory.openSession();

    try {

        //set transaction timeout to 3 seconds

        sess.getTransaction().setTimeout(3);

        sess.getTransaction().begin();

        // do some work

        ...

        sess.getTransaction().commit()

    }

    catch (RuntimeException e) {

        sess.getTransaction().rollback();

        throw e; // or display error message

    }

    finally {

        sess.close();

    }

CMT Bean の中では `setTimeout()` を呼び出せないことに注意してください。トランザクションタイムアウトは宣言的に定義されるべきです。

## 13.3. 楽観的同時実行制御

高い並列性と高いスケーラビリティの両方を実現するアプローチは、バージョニングを使った楽観的同時実行制御のみです。更新の衝突を見つけるために（および、更新が失われるのを防ぐために）、バージョン番号もしくはタイムスタンプを使って、バージョンをチェックします。 Hibernate は、楽観的同時実行を行うアプリケーションコードを書くためのアプローチを３つ提供します。私たちが見せるユースケースは、長い対話を持ちますが、バージョンチェックはまだ１つのデータベーストランザクションの中で更新を失うことを防ぐ利点も持っています。

### 13.3.1. アプリケーションによるバージョンチェック

Hibernate にほとんど助けてもらわずに実装するケースです。データベースとのやり取りは、それぞれ新しい `Session` の中で起こります。開発者は、すべての永続性インスタンスを操作する前に、データベースから再読み込みする責務があります。このアプローチでは、対話トランザクションの分離を守るために、アプリケーション自身がバージョンチェックを行う必要があります。このアプローチは、データベースアクセスの中では、最も非効率です。エンティティ EJB と最も似ているアプローチです。

    // foo is an instance loaded by a previous Session

    session = factory.openSession();

    Transaction t = session.beginTransaction();

    int oldVersion = foo.getVersion();

    session.load( foo, foo.getKey() ); // load the current state

    if ( oldVersion != foo.getVersion() ) throw new StaleObjectStateException();

    foo.setProperty("bar");

    t.commit();

    session.close();

`<version>` を使って、 `version` プロパティをマッピングします。 Hibernate は、エンティティがダーティである場合、フラッシュし、その間に `version` プロパティを自動的にインクリメントします。

もちろん、データの並列性が低い環境で運用しており、バージョンチェックが不要なら、このアプローチを使い、バージョンチェックをスキップするだけです。その場合は、長い対話には、 最後にコミットしたものが勝つ がデフォルトの戦略でしょう。このアプローチは、アプリケーションのユーザーを混乱させるかもしれないことを心に留めて置いてください。それは、エラーメッセージや競合した変更をマージする機会がないまま、更新を失う可能性があるからです。

確かに、マニュアルによるバージョンチェックは、些細な儀式だけで実行できますが、多くのアプリケーションにとって実用的ではありません。しばしば、１つのインスタンスだけでなく、修正されたオブジェクトの完全なグラフをチェックしなければなりません。 Hibernate は、設計パラダイムとして、拡張 `Session` か分離されたインスタンスを自動的にバージョンチェックします。

### 13.3.2. 拡張セッションと自動バージョニング

１つの `Session` インスタンスとその永続性インスタンスは、 session-per-conversation として知られる、対話全体で使われます。 Hibernate はフラッシュする際に、インスタンスのバージョンをチェックします。同時に修正されたことを検出すると、例外を投げます。この例外をキャッチして扱うのは、開発者の責任です （一般的な選択肢は、変更をマージするか古くないデータでビジネス対話を再スタートする機会をユーザーに提供することです）。

ユーザーの対話を待っているときは、 `Session` を基礎となる JDBC コネクションから切り離します。このアプローチは、データベースアクセスの中では、最も効率的です。アプリケーションは、バージョンチェックや分離されたインスタンスを再追加することに関心を持つ必要はありません。また、あらゆるデータベーストランザクションの中でインスタンスを再読み込みする必要はありません。

    // foo is an instance loaded earlier by the old session

    Transaction t = session.beginTransaction(); // Obtain a new JDBC connection, start transaction

    foo.setProperty("bar");

    session.flush();    // Only for last transaction in conversation

    t.commit();         // Also return JDBC connection

    session.close();    // Only for last transaction in conversation

`foo` オブジェクトは、自分をロードした `Session` をまだ知っています。古いセッションの上で新しいデータベーストランザクションを開始することで、新しいコネクションを取得し、そのセッションが再開されます。データベーストランザクションをコミットすることで、セッションから JDBC コネクションを切断し、コネクションをプールに返します。再接続した後、更新していないデータのバージョンチェックを強制するために、他のトランザクションにより更新されているかもしれないオブジェクトに関して、 `LockMode.READ` をつけて `Session.lock()` を呼び出すことができます。更新して いる データをロックする必要はありません。通常、拡張 `Session` に `FlushMode.MANUAL` をセットします。最後のデータベーストランザクションの周期でのみ、対話の中で変更されたすべてを実際に永続化させるためです。ゆえに、最後のデータベーストランザクションのみ `flush()` オペレーションを含みます。そして、対話を終わらせるために、セッションも `close()` します。

ユーザーが考慮中に、格納することができないくらい `Session` が大きいのであれば、このパターンは問題があります。例えば、 `HttpSession` は可能な限り小さく保つべきです。 `Session` は （強制的に） １次キャッシュでもあり、ロードしたオブジェクトをすべて保持します。おそらく、リクエスト／レスポンスのサイクルが数回であれば、この戦略が使えます。１つの対話のためだけに `Session` を使うべきです。なぜなら、すぐに新鮮でないデータを持つためです。

## 注記

Hibernate の以前のバージョンは、明示的な `Session` の切断と再接続が必要だったことに注意してください。これらのメソッドは非推奨になりました。なぜなら、トランザクションの開始と終了は同じ効果があるためです。

切断した `Session` を永続化層の近くで保持すべきであることに注意してください。言い換えると、３層環境の中で `Session` を保持するために、 EJB ステートフルセッション Bean を使ってください。 `HttpSession` に格納するために、 Web 層に転送しないでください （別の層へのシリアライズもしないでください）。

拡張セッションパターン （もしくは、 session-per-conversation ） は、自動的なカレントセッションコンテキスト管理を実施するより難しい。このために、あなたは `CurrentSessionContext` の実装を供給する必要があります。 Hibernate Wiki にある例を参照してください。

### 13.3.3. デタッチされたオブジェクトと自動バージョニング

新しい `Session` により、永続化ストア （訳注：ＤＢ） との対話が発生します。また一方、同じ永続性インスタンスが、データベースとの対話ごとに再利用されます。アプリケーションは、元々は他の `Session` でロードされ、デタッチされたインスタンスの状態を操作します。そして、 `Session.update()` もしくは、 `Session.saveOrUpdate()` 、 `Session.merge()` を使って、それらのインスタンスを再追加します。

    // foo is an instance loaded by a previous Session

    foo.setProperty("bar");

    session = factory.openSession();

    Transaction t = session.beginTransaction();

    session.saveOrUpdate(foo); // Use merge() if "foo" might have been loaded already

    t.commit();

    session.close();

この場合もやはり、 Hibernate はフラッシュする際に、インスタンスのバージョンをチェックします。更新の競合が発生した場合には、例外を投げます。

オブジェクトが修正されていないことを確信している場合は、 `update()` の代わりに、 `LockMode.READ` を使って、 `lock()` を呼び出すこともできます （すべてのキャッシュを迂回し、バージョンチェックを実施します）。

### 13.3.4. 自動バージョニングのカスタマイズ

マッピングの `optimistic-lock` 属性に `false` を設定することにより、特定のプロパティやコレクションのために自動バージョンインクリメントを無効にできます。プロパティがダーティであっても、バージョンをインクリメントしません。

レガシーのデータベーススキーマは、しばしば固定的であり、変更できません。または、他のアプリケーションが同じデータベースにアクセスしなければならず、そのアプリケーションはバージョン番号やタイムスタンプさえ操作する方法を知りません。どちらの場合も、テーブルの特定のカラムを当てにして、バージョニングを行えません。バージョンやタイムスタンプのプロパティをマッピングせずに、バージョンチェックさせるために、 `<class>` マッピングに `optimistic-lock="all"` を指定してください。行のすべてのフィールドの状態を比較するようになります。これは、 Hibernate が古い状態と新しい状態を比較できる場合に、理論的に動作するだけであることに注意してください。例えば、 session-per-request-with-detached-objects ではなく、１つの長い `Session` を使う場合です。

ときどき、行われた変更が重ならない限り、同時に行われた変更を受け入れることができます。 `<class>` マッピングに `optimistic-lock="dirty"` を設定した場合、フラッシュする際に、 Hibernate はダーティフィールドのみを比較します。

専用のバージョン／タイムスタンプのカラムを使う場合、もしくはすべて／ダーティのフィールドを比較する場合どちらであっても、 Hibernate はエンティティごとに1つの `UPDATE` 文を （適切な `WHERE` 節と共に） 使い、バージョンチェックと情報の更新を行います。関連するエンティティの再追加をカスケードするために、連鎖的な永続化を使用した場合、不必要な更新を実行するかもしれません。これは通常問題になりません。しかし、分離したインスタンスを変更していなくとも、データベースの on update トリガーが実行されるかもしれません。 `<class>` マッピングに `select-before-update="true"` を設定することによって、この振る舞いをカスタマイズできます。確実に変更されたかを確認するために、行を更新する前に、必ずインスタンスを `SELECT` します。

## 13.4. 悲観的ロック

ユーザーがロック戦略に悩むのに多くの時間を費やすことを意図していません。通常は、 JDBC コネクションに分離レベルを指定し、単にデータベースにすべての仕事をさせれば十分です。しかしながら、高度なユーザーは、排他的な悲観的ロックを獲得することか、新しいトランザクションが開始される際にロックを再獲得することをときどき望むかもしれません。

Hibernate はいつもデータベースのロックの仕組みを使います。メモリ内のオブジェクトを決してロックしません。

`LockMode` クラスは、 Hibernate が獲得できる異なるロックレベルを定義します。以下の仕組みにより、ロックを獲得できます。

- `LockMode.WRITE` は、 Hibernate が行を更新もしくは挿入する際に自動的に得られます。

- `LockMode.UPGRADE` は、データベースでサポートされている文法 `SELECT ... FOR UPDATE` を使った、明示的なユーザー要求により得られるかもしれません。

- `LockMode.UPGRADE_NOWAIT` は、 Oracle で `SELECT ... FOR UPDATE NOWAIT` を使った、明示的なユーザー要求により得られるかもしれません。

- `LockMode.READ` は、 Repeatable Read もしくは Serializable の分離レベルで、データを読んだ際に自動的に得られます。おそらく、明示的なユーザー要求により、再取得されます。

- `LockMode.NONE` は、ロックしないことを表します。 `Transaction` の終わりに、すべてのオブジェクトはこのロックモードに切り替わります。 `update()` や `saveOrUpdate()` を呼び出すことによって、セッションに関連付けられたオブジェクトも、このロックモードで出発します。

「明示的なユーザー要求」とは、下記の方法の１つで言い表せます。

- `LockMode` を指定した `Session.load()` の呼び出し。

- `Session.lock()` の呼び出し。

- `Query.setLockMode()` の呼び出し。

`UPGRADE` もしくは `UPGRADE_NOWAIT` が指定された `Session.load()` が呼び出され、かつ要求されたオブジェクトがセッションによってまだロードされていなかった場合は、 `SELECT ... FOR UPDATE` を使って、オブジェクトがロードされます。 `load()` で呼び出されたオブジェクトが、要求されているより制限が少ないロックですでにロードされていた場合は、 Hibernate はそのオブジェクトのために、 `lock()` を呼び出します。

指定されたロックモードが `READ` もしくは、 `UPGRADE` 、 `UPGRADE_NOWAIT` だった場合、 `Session.lock()` は、バージョン番号のチェックを実施します。 （`UPGRADE` もしくは `UPGRADE_NOWAIT` の場合、 `SELECT ... FOR UPDATE` が使われます。）

データベースが要求されたロックモードをサポートしていない場合、 Hibernate は（例外を投げる代わりに、）適切な代わりのモードを使います。これは、アプリケーションがポータブルであることを保証します。

## 13.5. コネクション開放モード

Hibernate のレガシー（2.x）の JDBC コネクション管理に関する振る舞いは、最初に必要とした際に `Session` がコネクションを得るというものでした。そして、セッションが閉じられるまで、そのコネクションを保持しました。 Hibernate 3.x は、セッションに JDBC コネクションをどのように制御するかを伝えるコネクション開放モードという概念を導入しました。以降の議論は、構成された `ConnectionProvider` を通して提供されるコネクションに適切であることに注意してください。異なる開放モードは、 `org.hibernate.ConnectionReleaseMode` に列挙された値により確認されます。

- `ON_CLOSE` - 本質的に上記で述べたレガシーの振る舞いです。 Hibernate セッションは最初に JDBC アクセスを実行する必要がある際にコネクションを得ます。そして、セッションが閉じられるまで、コネクションを保持します。

- `AFTER_TRANSACTION` - `org.hibernate.Transaction` が完了した後、コネクションを開放します。

- `AFTER_STATEMENT` （積極的な開放とも呼ばれる） - すべてのステートメントがそれぞれ実行された後、コネクションが開放されます。ステートメントがセッションに関連するリソースを開いたままにする場合は、この積極的な開放はスキップされます。今のところ、これが起こるのは `org.hibernate.ScrollableResults` が使われる場合のみです。

コンフィグレーションパラメータの `hibernate.connection.release_mode` は、使用する開放モードを指定するために使います。指定できる値は次の通りです:

- `auto` （デフォルト） - これを選択すると `org.hibernate.transaction.TransactionFactory.getDefaultReleaseMode()` メソッドによって返される開放モードに委譲されます。このメソッドは、 JTATransactionFactory には ConnectionReleaseMode.AFTER_STATEMENT を返し、 JDBCTransactionFactory には ConnectionReleaseMode.AFTER_TRANSACTION を返します。このデフォルトの振る舞いを変えてうまくいった試しがありません。それは、この設定値が原因で起こる障害は、ユーザーコードの中でバグや間違った条件になりやすいからです。

- `on_close` - ConnectionReleaseMode.ON_CLOSE を使います。この設定は後方互換のために残されていますが、使わないことを強く勧めます。

- `after_transaction` - ConnectionReleaseMode.AFTER_TRANSACTION を使います。この設定は JTA 環境の中では使うべきではありません。 ConnectionReleaseMode.AFTER_TRANSACTION を指定し、自動コミットモードの中では、開放モードが AFTER_STATEMENT であるかのように、コネクションは開放されることに注意してください。

- `after_statement` - ConnectionReleaseMode.AFTER_STATEMENT を使います。さらに、設定された `ConnectionProvider` は、この設定 (`supportsAggressiveRelease()`) をサポートするかどうかを調べるために使用します。もしそうでない場合、開放モードは ConnectionReleaseMode.AFTER_TRANSACTION にリセットされます。この設定は次の環境でのみ安全です。それは、 `ConnectionProvider.getConnection()` を呼び出すたびに基盤となる JDBC コネクションが同じものを取得できるか、同じコネクションが得られることが問題とならない自動コミット環境の中です。

## 第14章 インターセプタとイベント

アプリケーションが Hibernate の内部で発生するイベントに対応できると役に立つことがあります。ある種の一般的な機能を実装できるようになり、また Hibernate の機能を拡張することもできるようになります。

## 14.1. インターセプタ

`Interceptor` インターフェースを使って、セッションからアプリケーションへコールバックをすることができます。これにより永続オブジェクトの保存、更新、削除、読み込みの前に、アプリケーションがプロパティを検査したり操作したりできるようになります。これは監査情報の追跡に利用できます。下の例で `Interceptor` は `Auditable` が作成されると自動的に `createTimestamp` を設定し、 `Auditable` が更新されると自動的に `lastUpdateTimestamp` プロパティを更新します。

`Interceptor` を直接実装したり、 （さらによいのは） `EmptyInterceptor` を拡張したりできます。

    package org.hibernate.test;

    import java.io.Serializable;

    import java.util.Date;

    import java.util.Iterator;

    import org.hibernate.EmptyInterceptor;

    import org.hibernate.Transaction;

    import org.hibernate.type.Type;

    public class AuditInterceptor extends EmptyInterceptor {

        private int updates;

        private int creates;

        private int loads;

        public void onDelete(Object entity,

                             Serializable id,

                             Object[] state,

                             String[] propertyNames,

                             Type[] types) {

            // do nothing

        }

        public boolean onFlushDirty(Object entity,

                                    Serializable id,

                                    Object[] currentState,

                                    Object[] previousState,

                                    String[] propertyNames,

                                    Type[] types) {

            if ( entity instanceof Auditable ) {

                updates++;

                for ( int i=0; i < propertyNames.length; i++ ) {

                    if ( "lastUpdateTimestamp".equals( propertyNames[i] ) ) {

                        currentState[i] = new Date();

                        return true;

                    }

                }

            }

            return false;

        }

        public boolean onLoad(Object entity,

                              Serializable id,

                              Object[] state,

                              String[] propertyNames,

                              Type[] types) {

            if ( entity instanceof Auditable ) {

                loads++;

            }

            return false;

        }

        public boolean onSave(Object entity,

                              Serializable id,

                              Object[] state,

                              String[] propertyNames,

                              Type[] types) {

            if ( entity instanceof Auditable ) {

                creates++;

                for ( int i=0; i<propertyNames.length; i++ ) {

                    if ( "createTimestamp".equals( propertyNames[i] ) ) {

                        state[i] = new Date();

                        return true;

                    }

                }

            }

            return false;

        }

        public void afterTransactionCompletion(Transaction tx) {

            if ( tx.wasCommitted() ) {

                System.out.println("Creations: " + creates + ", Updates: " + updates, "Loads: " + loads);

            }

            updates=0;

            creates=0;

            loads=0;

        }

    }

インターセプタには二種類あります： `Session` スコープのものと `SessionFactory` スコープのものです。

`Session` スコープのインターセプタは、セッションをオープンするときに指定します。 `Interceptor` を引数に取る SessionFactory.openSession() のオーバーロードメソッドの一つを使います。

    Session session = sf.openSession( new AuditInterceptor() );

`SessionFactory` スコープのインターセプタは `Configuration` オブジェクトを使って登録します。これは `SessionFactory` の構築よりも優先されます。この場合、提供されるインターセプタは `SessionFactory` からオープンされたすべてのセッションに適用されます。これは使用するインターセプタを明示的に指定してセッションをオープンしない限り、そうなります。 `SessionFactory` スコープのインターセプタはスレッドセーフでなければなりません。複数のセッションが （潜在的に） このインターセプタを同時並行で使用することになるため、セッション固有の状態を格納しないように気をつけてください。

    new Configuration().setInterceptor( new AuditInterceptor() );

## 14.2. イベントシステム

永続化層で特定のイベントに対応しなければならない場合、 Hibernate3 の イベント アーキテクチャを使うこともできます。イベントシステムはインターセプタと一緒に使うか、またはインターセプタの代わりとして使うことができます。

本質的に `Session` インターフェースのすべてのメソッドは、1個のイベントと相互に関連します。例えば `LoadEvent` 、 `FlushEvent` などがあります （定義済みのイベント型の一覧については、 XML 設定ファイルの DTD や `org.hibernate.event` パッケージを調べてください） 。リクエストがこれらのメソッドの1つから作られるとき、 Hibernate の `Session` は適切なイベントを生成し、そのイベント型に設定されたイベントリスナに渡します。すばらしいことに、これらのリスナはそのメソッドと同じ処理を実装します。とはいえ、リスナインターフェースの一つを自由にカスタム実装できます （つまり、 `LoadEvent` は登録された `LoadEventListener` インターフェースの実装により処理されます）。その場合、その実装には `Session` から作られたどのような `load()` リクエストをも処理する責任があります。

リスナは事実上シングルトンであると見なせます。つまりリスナはリクエスト間で共有されるため、インスタンス変数として状態を保持するべきではないということです。

カスタムリスナは処理したいイベントについて適切なインターフェースを実装するべきです。便利な基底クラスのうちの一つを継承してもよいです （または Hibernate がデフォルトで使用するイベントリスナを継承してもよいです。すばらしいことに、この目的のために非 final として宣言されています） 。カスタムリスナは `Configuration` オブジェクトを使ってプログラムから登録するか、 Hibernate の XML 設定ファイルで指定できます （プロパティファイルで宣言的に設定する方法はサポートされていません） 。カスタムロードイベントリスナの例を示します:

    public class MyLoadListener implements LoadEventListener {

        // this is the single method defined by the LoadEventListener interface

        public void onLoad(LoadEvent event, LoadEventListener.LoadType loadType)

                throws HibernateException {

            if ( !MySecurity.isAuthorized( event.getEntityClassName(), event.getEntityId() ) ) {

                throw MySecurityException("Unauthorized access");

            }

        }

    }

デフォルトリスナ以外のリスナを使うには、 Hibernate への設定も必要です：

    <hibernate-configuration>

        <session-factory>

            ...

            <event type="load">

                <listener class="com.eg.MyLoadListener"/>

                <listener class="org.hibernate.event.def.DefaultLoadEventListener"/>

            </event>

        </session-factory>

    </hibernate-configuration

    >

またその他に、プログラムで登録する方法もあります：

    Configuration cfg = new Configuration();

    LoadEventListener[] stack = { new MyLoadListener(), new DefaultLoadEventListener() };

    cfg.EventListeners().setLoadEventListeners(stack);

リスナを宣言的に登録すると、そのリスナのインスタンスを共有できません。複数の `<listener/>` 要素で同じクラス名が使われると、それぞれの参照はそのクラスの別々のインスタンスを指すことになります。リスナ型の間でリスナインスタンスを共有する必要があれば、プログラムで登録する方法を採らなければなりません。

なぜインターフェースを実装して、特化した型を設定時に指定するのでしょうか？リスナの実装クラスに、複数のイベントリスナインターフェースを実装できるからです。登録時に追加で型を指定することで、カスタムリスナの on/off を設定時に簡単に切り替えられます。

## 14.3. Hibernate の宣言的なセキュリティ

一般的に Hibernate アプリケーションの宣言的なセキュリティは、セッションファサード層で管理します。現在、 Hiberenate3 は JACC で許可し、さらに JAAS で認証したアクションを許しています。これはイベントアーキテクチャの最上位に組み込まれているオプションの機能です。

まず最初に、適切なイベントリスナを設定して JAAS 認証を使えるようにしなければなりません。

    <listener type="pre-delete" class="org.hibernate.secure.JACCPreDeleteEventListener"/>

    <listener type="pre-update" class="org.hibernate.secure.JACCPreUpdateEventListener"/>

    <listener type="pre-insert" class="org.hibernate.secure.JACCPreInsertEventListener"/>

    <listener type="pre-load" class="org.hibernate.secure.JACCPreLoadEventListener"/>

特定のイベント型に対してちょうど一つのリスナがあるとき、 `<listener type="..." class="..."/>` は `<event type="..."><listener class="..."/></event>` の簡略形に過ぎないことに注意してください。

次に、同じく `hibernate.cfg.xml` でロールにパーミッションを与えてください：

    <grant role="admin" entity-name="User" actions="insert,update,read"/>

    <grant role="su" entity-name="User" actions="*"/>

このロール名は使用する JACC プロバイダに理解されるロールです。

## 第15章 バッチ処理

Hibernate を使ってデータベースに100,000行を挿入する愚直な方法は、このようなものです：

    Session session = sessionFactory.openSession();

    Transaction tx = session.beginTransaction();

    for ( int i=0; i<100000; i++ ) {

        Customer customer = new Customer(.....);

        session.save(customer);

    }

    tx.commit();

    session.close();

これは50,000番目の行のあたりで `OutOfMemoryException` で失敗するでしょう。 Hibernate がセッションレベルキャッシュで、新しく挿入されたすべての `Customer` インスタンスをキャッシュするからです。

この章では、この問題を回避する方法を紹介します。しかしバッチ処理をするなら、 JDBC バッチが使用可能であることが非常に重要です。そうでなければ手頃なパフォーマンスが得られません。 JDBC バッチサイズを手頃な数値（例えば、10から50）に設定してください：

    hibernate.jdbc.batch_size 20

`identiy` 識別子生成を使う場合は、Hibernate は JDBC レベルでインサートバッチングを無効にすることに注意してください。

また二次キャッシュが全く効かないプロセスで、このような作業をしたいと思うかもしれません：

    hibernate.cache.use_second_level_cache false

しかし、これは絶対に必要というわけではありません。なぜなら明示的に `CacheMode` を設定して、二次キャッシュとの相互作用を無効にすることができるからです。

## 15.1. バッチ挿入

新しいオブジェクトを永続化するとき、一次キャッシュのサイズを制限するため、セッションを `flush()` して `clear()` しなければなりません。

    Session session = sessionFactory.openSession();

    Transaction tx = session.beginTransaction();

    for ( int i=0; i<100000; i++ ) {

        Customer customer = new Customer(.....);

        session.save(customer);

        if ( i % 20 == 0 ) { //20, same as the JDBC batch size

            //flush a batch of inserts and release memory:

            session.flush();

            session.clear();

        }

    }

    tx.commit();

    session.close();

## 15.2. バッチ更新

データを復元したり更新したりするには同じアイディアを適用します。それに加えて、データの行を多く返すクエリに対して有効なサーバーサイドのカーソルの利点を生かしたければ `scroll()` を使う必要があります。

    Session session = sessionFactory.openSession();

    Transaction tx = session.beginTransaction();

    ScrollableResults customers = session.getNamedQuery("GetCustomers")

        .setCacheMode(CacheMode.IGNORE)

        .scroll(ScrollMode.FORWARD_ONLY);

    int count=0;

    while ( customers.next() ) {

        Customer customer = (Customer) customers.get(0);

        customer.updateStuff(...);

        if ( ++count % 20 == 0 ) {

            //flush a batch of updates and release memory:

            session.flush();

            session.clear();

        }

    }

    tx.commit();

    session.close();

## 15.3. StatelessSession インターフェース

また別の方法として、 Hibernate はコマンド指向の API を用意しています。これは分離オブジェクトの形で、データベースとのデータストリームのやり取りに使うことができます。 `StatelessSession` は関連する永続コンテキストを持たず、高レベルのライフサイクルセマンティクスの多くを提供しません。特にステートレスセッションは、一次キャッシュを実装せず、またどのような二次キャッシュやクエリキャッシュとも相互作用しません。トランザクショナルな write-behind や自動ダーティチェックも実装しません。ステートレスセッションを使って行われる操作が、関連するインスタンスへカスケードされることは決してありません。コレクションは、ステートレスセッションからは無視されます。ステートレスセッションを通して行われる操作は、 Hibernate のイベントモデルやインターセプタの影響を受けません。一次キャッシュを持たないため、ステートレスセッションは別名を持つデータに上手く対処できません。ステートレスセッションは低レベルの抽象化であり、 JDBC に非常によく似ています。

    StatelessSession session = sessionFactory.openStatelessSession();

    Transaction tx = session.beginTransaction();

    ScrollableResults customers = session.getNamedQuery("GetCustomers")

        .scroll(ScrollMode.FORWARD_ONLY);

    while ( customers.next() ) {

        Customer customer = (Customer) customers.get(0);

        customer.updateStuff(...);

        session.update(customer);

    }

    tx.commit();

    session.close();

このコード例では、クエリが返す `Customer` インスタンスは即座に （セッションから） 分離されることに注意してください。これは、どのような永続コンテキストとも決して関連しません。

`StatelessSession` インターフェースで定義されている `insert(), update()` と `delete()` の操作は、低レベルの直接的なデータベース操作と考えられます。結果として、 SQL の `INSERT, UPDATE` または `DELETE` がそれぞれ即座に実行されます。このように、これらは `Session` インターフェースで定義されている `save(), saveOrUpdate()` と `delete()` とは非常に異なる意味を持ちます。

## 15.4. DML スタイルの操作

As already discussed, automatic and transparent object/relational mapping is concerned with the management of the object state. The object state is available in memory. This means that manipulating data directly in the database (using the SQL `Data Manipulation Language` (DML) the statements: `INSERT`, `UPDATE`, `DELETE`) will not affect in-memory state. However, Hibernate provides methods for bulk SQL-style DML statement execution that is performed through the Hibernate Query Language (HQL).

`UPDATE` と `DELETE` 文の疑似構文は： `( UPDATE | DELETE ) FROM? エンティティ名 (WHERE 条件節)?` です。注意すべき点がいくつかあります：

Some points to note:

- from 節において、 FROM キーワードはオプションです。

- from 節では単一のエンティティ名だけが可能で、任意で別名を付けることができます。エンティティ名に別名が与えられると、どのようなプロパティ参照も、その別名を使って修飾しなければなりません。もしエンティティ名に別名が与えられなければ、どのようなプロパティ参照も修飾してはなりません。

- No joins, either implicit or explicit, can be specified in a bulk HQL query. Sub-queries can be used in the where-clause, where the subqueries themselves may contain joins.

- where 節はオプションです。

例として、 HQL の `UPDATE` を実行するには、 `Query.executeUpdate()` メソッドを使ってください。（このメソッドはおなじみの JDBC `PreparedStatement.executeUpdate()` から名付けられました）：

    Session session = sessionFactory.openSession();

    Transaction tx = session.beginTransaction();

    String hqlUpdate = "update Customer c set c.name = :newName where c.name = :oldName";

    // or String hqlUpdate = "update Customer set name = :newName where name = :oldName";

    int updatedEntities = s.createQuery( hqlUpdate )

            .setString( "newName", newName )

            .setString( "oldName", oldName )

            .executeUpdate();

    tx.commit();

    session.close();

In keeping with the EJB3 specification, HQL `UPDATE` statements, by default, do not effect the version or the timestamp property values for the affected entities. However, you can force Hibernate to reset the `version` or `timestamp` property values through the use of a `versioned update`. This is achieved by adding the `VERSIONED` keyword after the `UPDATE` keyword.

    Session session = sessionFactory.openSession();

    Transaction tx = session.beginTransaction();

    String hqlVersionedUpdate = "update versioned Customer set name = :newName where name = :oldName";

    int updatedEntities = s.createQuery( hqlUpdate )

            .setString( "newName", newName )

            .setString( "oldName", oldName )

            .executeUpdate();

    tx.commit();

    session.close();

カスタムバージョン型（`org.hibernate.usertype.UserVersionType`）は `update versioned` 文と一緒に使えないことに注意してください。

HQL の `DELETE` を実行するには、同じ `Query.executeUpdate()` メソッドを使ってください：

    Session session = sessionFactory.openSession();

    Transaction tx = session.beginTransaction();

    String hqlDelete = "delete Customer c where c.name = :oldName";

    // or String hqlDelete = "delete Customer where name = :oldName";

    int deletedEntities = s.createQuery( hqlDelete )

            .setString( "oldName", oldName )

            .executeUpdate();

    tx.commit();

    session.close();

`Query.executeUpdate()` メソッドが返す `int` の値は、この操作が影響を及ぼしたエンティティの数です。これが影響するデータベース内の行数と、相互に関係するかどうかを考えてみてください。 HQL バルク操作は、結果として、実際の SQL 文が複数実行されることになります。例えば joined-subclass です。返される数は、その文によって影響された実際のエンティティの数を示します。 joined-subclass の例に戻ると、サブクラスの一つに対する削除は、そのサブクラスがマッピングされたテーブルだけではなく、「ルート」テーブルと継承階層をさらに下った joined-subclass のテーブルの削除になります。

`INSERT` 文の疑似構文は： `INSERT INTO エンティティ名プロパティリスト select 文` です。注意すべき点がいくつかあります：

- INSERT INTO ... SELECT ... の形式だけがサポートされています。 INSERT INTO ... VALUES ... の形式はサポートされていません。

  プロパティリストは、 SQL の `INSERT` 文における `カラムの仕様` に類似しています。継承のマッピングに含まれるエンティティに対して、クラスレベルで直接定義されたプロパティだけが、プロパティリストに使えます。スーパークラスのプロパティは認められず、サブクラスのプロパティは効果がありません。言い換えると `INSERT` 文は、本質的にポリモーフィックではありません。

- select 文の返り値の型が insert 文が期待する型とマッチしていれば、その select 文は妥当な HQL select クエリとなりえます。現在このチェックをデータベースへ任せるのではなく、クエリのコンパイル時にチェックします。このことは、 equal とは違い、 Hibernate の `Type` 間の equivalent に関する問題を引き起こすことに注意してください。これは `org.hibernate.type.DateType` として定義されたプロパティと、 `org.hibernate.type.TimestampType` として定義されたプロパティの間のミスマッチの問題を引き起こします。データベースがそれらを区別できなくても、変換することができても、この問題は発生します。

- id プロパティに対して、 insert 文には二つの選択肢があります。プロパティリストで明示的に id プロパティを指定するか （この場合、対応する select 式から値が取られます）、プロパティリストからそれを除外するかのいずれかです (この場合、生成される値が使われます)。 後者の選択肢は、データベース内を操作する id ジェネレータを使うときのみ、利用可能です。この選択肢を採る場合、「インメモリ」型のジェネレータを使うと、構文解析時に例外が発生します。この議論では、インデータベース型ジェネレータは `org.hibernate.id.SequenceGenerator` （とそのサブクラス） と、 `org.hibernate.id.PostInsertIdentifierGenerator` の実装であると考えています。ここで最も注意すべき例外は、 `org.hibernate.id.TableHiLoGenerator` です。値を取得する選択可能な方法がないため、このジェネレータを使うことはできません。

- `version` や `timestamp` としてマッピングされるプロパティに対して、 insert 文には二つの選択肢があります。プロパティリストで明示的にプロパティを指定するか（この場合、対応する select 式から値が取られます）、プロパティリストから除外するか（この場合、 `org.hibernate.type.VersionType` で定義された `シード値` が使われます）のいずれかです。

HQL の `INSERT` 文の実行例です：

    Session session = sessionFactory.openSession();

    Transaction tx = session.beginTransaction();

    String hqlInsert = "insert into DelinquentAccount (id, name) select c.id, c.name from Customer c where ...";

    int createdEntities = s.createQuery( hqlInsert )

            .executeUpdate();

    tx.commit();

    session.close();

## 第16章 HQL: Hibernate クエリ言語

Hibernate は SQL に非常によく似た (意図的に似せた) 強力な問い合わせ言語を備えています。しかし SQL に似た構文に惑わされないでください。 HQL は完全にオブジェクト指向であり、継承、ポリモーフィズム、関連といった概念を理解します。

## 16.1. 大文字と小文字の区別

クエリは Java のクラス名とプロパティ名を除いて大文字、小文字を区別しません。従って `SeLeCT` は `sELEct` と同じで、かつ `SELECT` とも同じですが `org.hibernate.eg.FOO` は `org.hibernate.eg.Foo` とは違い、かつ `foo.barSet` は `foo.BARSET` とも違います。

このマニュアルでは小文字の HQL キーワードを使用します。大文字のキーワードのクエリの方が読みやすいと感じるユーザーもいると思います。ですが、 Java コード内に埋め込まれたときには見づらいと思います。

## 16.2. from 節

もっとも単純な Hibernate クエリは次の形式です:

    from eg.Cat

This returns all instances of the class `eg.Cat`. You do not usually need to qualify the class name, since `auto-import` is the default. For example:

    from Cat

In order to refer to the `Cat` in other parts of the query, you will need to assign an alias. For example:

    from Cat as cat

このクエリでは `Cat` インスタンスに `cat` という別名を付けています。そのため、後でこのクエリ内で、この別名を使うことができます。 `as` キーワードはオプションです。つまりこのように書くこともできます：

    from Cat cat

直積、あるいは「クロス」結合によって多数のクラスが出現することもあります。

    from Formula, Parameter

    from Formula as form, Parameter as param

ローカル変数の Java のネーミング基準と一致した、頭文字に小文字を使ったクエリの別名を付けることはいい習慣です (例えば `domesticCat`)。

## 16.3. 関連と結合

関連するエンティティあるいは値コレクションの要素にも、 `結合` を使って別名を割り当てることが出来ます。

    from Cat as cat
        inner join cat.mate as mate
        left outer join cat.kittens as kitten

    from Cat as cat left join cat.mate.kittens as kittens

    from Formula form full join form.parameter param

サポートしている結合のタイプは ANSI SQL と同じです。

- `inner join`

- `left outer join`

- `right outer join`

- `full join` (たいていの場合使いづらい)

`inner join`、 `left outer join`、 `right outer join` には省略形を使うこともできます。

    from Cat as cat
        join cat.mate as mate
        left join cat.kittens as kitten

HQL の `with` キーワードを使うと、結合条件を付け加えることができます。

    from Cat as cat
        left join cat.kittens as kitten
            with kitten.bodyWeight
    > 10.0

A "fetch" join allows associations or collections of values to be initialized along with their parent objects using a single select. This is particularly useful in the case of a collection. It effectively overrides the outer join and lazy declarations of the mapping file for associations and collections. See 「フェッチ戦略」 for more information.

    from Cat as cat
        inner join fetch cat.mate
        left join fetch cat.kittens

結合によるフェッチは関連するオブジェクトが `where` 節 (または他のどんな節でも) で使われてはならないので、通常別名を割り当てる必要がありません。また関連オブジェクトは問い合わせ結果として直接返されません。代わりに親オブジェクトを通してアクセスできます。コレクションを再帰的に結合フェッチする場合のみ、別名が必要になります:

    from Cat as cat
        inner join fetch cat.mate
        left join fetch cat.kittens child
        left join fetch child.kittens

`fetch` 構文は `iterate()` を使ったクエリ呼び出しで使用できないことに注意してください （一方で `scroll()` は使用できます）。また、これらの操作は結果の行に基づいているため、 `fetch` は `setMaxResults()` や `setFirstResult()` と一緒に使用すべきではありません。通常 eager なコレクションフェッチをすると重複が出てしまうため、あなたが期待するような行数にはならないのです。そしてまた `fetch` は、アドホックな `with` 条件を一緒に使うこともできません。一つのクエリで複数のコレクションを結合フェッチすることにより直積を作成できるので、この場合注意してください。また、複数のコレクションに対する結合フェッチは bag マッピングに対して予期せぬ結果をもたらすことがあるので、この場合のクエリの作成には注意してください。最後に `全外部結合によるフェッチ` と `右外部結合によるフェッチ` は有用ではないことに注意してください。

もしプロパティレベルの遅延フェッチを使う場合（内部的にバイトコード処理をする場合）、 `fetch all properties` を使うことで Hibernate に遅延プロパティを速やかに（最初のクエリで）フェッチさせることができます。

    from Document fetch all properties order by name

    from Document doc fetch all properties where lower(doc.name) like '%cats%'

## 16.4. 結合構文の形式

HQL は２つの関連結合形式をサポートします： `暗黙的` と `明示的`。

これまでのセクションでお見せした使い方はすべて `明示的な` 形式で、 from 節で明示的に join キーワードを使っています。この形式をおすすめします。

`暗黙的` フォームは、 join キーワードを使いません。代わりに、参照する関連にドット表記を使います。 `暗黙的` 結合は、さまざまな HQL に出てきます。 `暗黙的` 結合の結果は、 SQL ステートメントの内部結合結果です。

    from Cat as cat where cat.mate.name like '%s%'

## 16.5. 識別子プロパティの参照

エンティティの識別子プロパティは、一般的に2つの方法で参照されます:

- 特別なプロパティ (小文字) `id` は、 id と名付けられた非識別子プロパティを定義しないエンティティを与えられた エンティティの識別子プロパティを参照するのに使用されます。

- もしエンティティが名付けられた識別子プロパティを定義したら、そのプロパティ名を使用できます。

複合識別子プロパティへの参照は同じ命名ルールに従います。もしエンティティが id と名付けられた非識別子プロパティを持っていたら、複合識別子プロパティはその定義された名前で参照することができます。そうでないと、特別な `id` プロパティは、識別子プロパティを参照するのに使用されます。

## 重要項目

注記: これは、バージョン 3.2.2 から大幅に変更しました。前バージョンでは、 `id` は、その実際の名前に関係なく 常に 識別子プロパティを参照していました。その結果、 `id` と名付けられた非識別子プロパティは、 Hibernate で決して参照されませんでした。

## 16.6. Select 節

`select` 節は以下のようにどのオブジェクトと属性をクエリリザルトセットに返すかを選択します:

    select mate
    from Cat as cat
        inner join cat.mate as mate

上記のクエリは他の `Cat` の `mate` を選択します。実際には次のように、より簡潔に表現できます:

    select cat.mate from Cat cat

クエリはコンポーネント型のプロパティを含む、あらゆる値型のプロパティも返せます:

    select cat.name from DomesticCat cat
    where cat.name like 'fri%'

    select cust.name.firstName from Customer as cust

クエリは複数のオブジェクトと (または) プロパティを `Object[]` 型の配列として返せます。

    select mother, offspr, mate.name
    from DomesticCat as mother
        inner join mother.mate as mate
        left outer join mother.kittens as offspr

もしくは `List` として、

    select new list(mother, offspr, mate.name)
    from DomesticCat as mother
        inner join mother.mate as mate
        left outer join mother.kittens as offspr

あるいは `Family` クラスが適切なコンストラクタを持っているとするならば、

    select new Family(mother, mate, offspr)
    from DomesticCat as mother
        join mother.mate as mate
        left join mother.kittens as offspr

select 節に `as` を使って別名をつけることもできます。

    select max(bodyWeight) as max, min(bodyWeight) as min, count(*) as n
    from Cat cat

`select new map` と一緒に使うときに最も役立ちます：

    select new map( max(bodyWeight) as max, min(bodyWeight) as min, count(*) as n )
    from Cat cat

このクエリは別名から select した値へ `Map` を返します。

## 16.7. 集約関数

HQL のクエリはプロパティの集約関数の結果も返せます：

    select avg(cat.weight), sum(cat.weight), max(cat.weight), count(cat)
    from Cat cat

サポートしている集約関数は以下のものです。

- `avg(...), sum(...), min(...), max(...)`

- `count(*)`

- `count(...), count(distinct ...), count(all...)`

select 節において算術操作、連結と承認された SQL 関数を使うことができます:

    select cat.weight + sum(kitten.weight)
    from Cat cat
        join cat.kittens kitten
    group by cat.id, cat.weight

    select firstName||' '||initial||' '||upper(lastName) from Person

SQL と同じ意味を持つ `distinct` と `all` キーワードを使うことができます。

    select distinct cat.name from Cat cat

    select count(distinct cat.name), count(cat) from Cat cat

## 16.8. ポリモーフィズムを使ったクエリ

次のようなクエリ：

    from Cat as cat

`Cat` インスタンスだけではなく、 `DomesticCat` のようなサブクラスも返されます。 Hibernate クエリは どんな Java クラスやインターフェースも `from` 節に入れることができます。クエリはそのクラスを拡張した、もしくはインターフェースを実装した全ての永続クラスを返します。次のクエリは永続オブジェクトをすべて返します:

    from java.lang.Object o

`Named` インターフェースは様々な永続クラスによって実装されます。:

    from Named n, Named m where n.name = m.name

最後の2つのクエリは、2つ以上の SQL `SELECT` を要求していることに注意してください。このことは `order by` 節がリザルトセット全体を正確には整列しないことを意味します (さらにそれは、 `Query.scroll()` を使用してこれらのクエリを呼ぶことができないことを意味します。)。

## 16.9. where 節

`where` 節は返されるインスタンスのリストを絞ることができます。もし別名がない場合、名前でプロパティを参照します。

    from Cat where name='Fritz'

もし別名がある場合、修飾名を使ってください:

    from Cat as cat where cat.name='Fritz'

名前が 'Fritz' という `Cat` のインスタンスを返します。

The following query:

    select foo
    from Foo foo, Bar bar
    where foo.startDate = bar.date

上の HQL は、 `Foo` の `startDate` プロパティと等しい `date` プロパティを持った `bar` インスタンスが存在する、すべての `Foo` インスタンスを返します。コンパウンドパス式は `where` 節を非常に強力にします。注目：

    from Cat cat where cat.mate.name is not null

このクエリはテーブル結合（内部結合）を持つ SQL クエリに変換されます。その代わりに以下のように書くと、

    from Foo foo
    where foo.bar.baz.customer.address.city is not null

もし上のクエリを記述したらクエリ内に4つのテーブル結合を必要とする SQL クエリに変換されます。

`=` 演算子は以下のように、プロパティだけでなくインスタンスを比較するためにも使われます。：

    from Cat cat, Cat rival where cat.mate = rival.mate

    select cat, mate
    from Cat cat, Cat mate
    where cat.mate = mate

The special property (lowercase) `id` can be used to reference the unique identifier of an object. See 「識別子プロパティの参照」 for more information.

    from Cat as cat where cat.id = 123

    from Cat as cat where cat.mate.id = 69

2番目のクエリは効率的です。テーブル結合が必要ありません。

また複合識別子のプロパティも使用できます。ここで `Person` が `country` と `medicareNumber` からなる複合識別子を持つと仮定します。識別子プロパティ参照についての詳細は、前回と同様に 「識別子プロパティの参照」 を参照ください。

    from bank.Person person
    where person.id.country = 'AU'
        and person.id.medicareNumber = 123456

    from bank.Account account
    where account.owner.id.country = 'AU'
        and account.owner.id.medicareNumber = 123456

繰り返しますが、2番目のクエリにはテーブル結合が必要ありません。

See 「識別子プロパティの参照」 for more information regarding referencing identifier properties)

同様に `class` は特別なプロパティであり、ポリモーフィックな永続化におけるインスタンスの discriminator 値にアクセスします。 where 節に埋め込まれた Java のクラス名はその discriminator 値に変換されます。

    from Cat cat where cat.class = DomesticCat

You can also use components or composite user types, or properties of said component types. See 「コンポーネント」 for more information.

"any" 型は特別なプロパティである `id` と `class` を持ち、以下の方法で結合を表現することを可能にします (`AuditLog.item` は `<any>` でマッピングされたプロパティです)。

    from AuditLog log, Payment payment
    where log.item.class = 'Payment' and log.item.id = payment.id

`log.item.class` と `payment.class` が上記のクエリ中で全く異なるデータベースカラムの値を参照するということに注意してください。

## 16.10. Expressions 式

Expressions used in the `where` clause include the following:

- 算術演算子：`+, -, *, /`

- 2項比較演算子：`=, >=, <=, <>, !=, like`

- 論理演算子：`and, or, not`

- グループ分けを表す括弧：`( )`

- `in`, `not in`, `between`, `is null`, `is not null`, `is empty`, `is not empty`, `member of` and `not member of`

- "シンプル"な case `case ... when ... then ... else ... end`、 "探索的"な case `case when ... then ... else ... end`

- ストリングの連結 `...||...` または `concat(...,...)`

- `current_date()`, `current_time()`, `current_timestamp()`

- `second(...)`, `minute(...)`, `hour(...)`, `day(...)`, `month(...)`, `year(...)`,

- EJB-QL 3.0 で定義されている関数や演算子: `substring(), trim(), lower(), upper(), length(), locate(), abs(), sqrt(), bit_length(), mod()`

- `coalesce()` と `nullif()`

- 数字や時間の値を String にコンバートする `str()`

- 2番目の引数が Hibernate 型の名前である `cast(... as ...)` と `extract(... from ...)`。ただし使用するデータベースが ANSI `cast()` と `extract()` をサポートする場合に限ります。

- 結合したインデックス付きのコレクションの別名に適用される HQL の `index()` 関数。

- コレクション値のパス式を取る HQL 関数： `size(), minelement(), maxelement(), minindex(), maxindex()` 。 `some, all, exists, any, in` を使って修飾することができる特別な `elements()` と `indices` 関数と一緒に使います。

- `sign()`、 `trunc()`、 `rtrim()`、 `sin()` のようなデータベースがサポートする SQL スカラ関数。

- JDBC スタイルの位置パラメータ `?`

- 名前付きパラメータ: `:name`, `:start_date`, `:x1`

- SQL リテラル： `'foo'`、 `69`、 `6.66E+2`、 `'1970-01-01 10:00:01.0'`

- Java の `public static final` 定数： `eg.Color.TABBY`

`in` と `between` は以下のように使用できます:

    from DomesticCat cat where cat.name between 'A' and 'B'

    from DomesticCat cat where cat.name in ( 'Foo', 'Bar', 'Baz' )

また、否定形で記述することもできます。

    from DomesticCat cat where cat.name not between 'A' and 'B'

    from DomesticCat cat where cat.name not in ( 'Foo', 'Bar', 'Baz' )

同様に `is null` や `is not null` は null 値をテストするために使用できます。

Hibernate 設定ファイルで HQL query substitutions を定義すれば、 boolean 値を式の中で簡単に使用できます：

    <property name="hibernate.query.substitutions"
    >true 1, false 0</property
    >

こうすることで下記の HQL を SQL に変換するときに `true` 、 `false` キーワードは `1` 、 `0` に置き換えられます:

    from Cat cat where cat.alive = true

特別なプロパティ `size`、または特別な関数 `size()` を使ってコレクションのサイズをテストできます:

    from Cat cat where cat.kittens.size
    > 0

    from Cat cat where size(cat.kittens)
    > 0

インデックス付きのコレクションでは、 `minindex` と `maxindex` 関数を使って、インデックスの最小値と最大値を参照できます。同様に、 `minelement` と `maxelement` を使って、基本型のコレクション要素の最小値と最大値を参照できます。

    from Calendar cal where maxelement(cal.holidays)
    > current_date

    from Order order where maxindex(order.items)
    > 100

    from Order order where minelement(order.items)
    > 10000

コレクションの要素やインデックスのセット（`elements` と `indices` 関数）、または副問い合わせ（後述）の結果が受け取れるときは、 SQL 関数 `any, some, all, exists, in` がサポートされます。

    select mother from Cat as mother, Cat as kit
    where kit in elements(foo.kittens)

    select p from NameList list, Person p
    where p.name = some elements(list.names)

    from Cat cat where exists elements(cat.kittens)

    from Player p where 3
    > all elements(p.scores)

    from Show show where 'fizard' in indices(show.acts)

`size`、 `elements`、 `indices`、 `minindex`、 `maxindex`、 `minelement`、 `maxelement` は Hibernate3 の where 節だけで利用可能であることに注意してください。

インデックス付きのコレクション（arrays, lists, maps）の要素は、インデックスで参照できます（where節内でのみ）：

    from Order order where order.items[0].id = 1234

    select person from Person person, Calendar calendar
    where calendar.holidays['national day'] = person.birthDay
        and person.nationality.calendar = calendar

    select item from Item item, Order order
    where order.items[ order.deliveredItemIndices[0] ] = item and order.id = 11

    select item from Item item, Order order
    where order.items[ maxindex(order.items) ] = item and order.id = 11

`[]` 内部の式は、算術式でも構いません。

    select item from Item item, Order order
    where order.items[ size(order.items) - 1 ] = item

一対多関連や値のコレクションの要素に対しては、 HQL は組み込みの `index()` 関数も用意しています。

    select item, index(item) from Order order
        join order.items item
    where index(item) < 5

ベースとなるデータベースがサポートしているスカラー SQL 関数が使用できます：

    from DomesticCat cat where upper(cat.name) like 'FRI%'

もしまだ全てを理解していないなら、下のクエリを SQL でどれだけ長く、読みづらく出来るか考えてください:

    select cust
    from Product prod,
        Store store
        inner join store.customers cust
    where prod.name = 'widget'
        and store.location.name in ( 'Melbourne', 'Sydney' )
        and prod = all elements(cust.currentOrder.lineItems)

ヒント: 例えばこのように出来ます。

    SELECT cust.name, cust.address, cust.phone, cust.id, cust.current_order
    FROM customers cust,
        stores store,
        locations loc,
        store_customers sc,
        product prod
    WHERE prod.name = 'widget'
        AND store.loc_id = loc.id
        AND loc.name IN ( 'Melbourne', 'Sydney' )
        AND sc.store_id = store.id
        AND sc.cust_id = cust.id
        AND prod.id = ALL(
            SELECT item.prod_id
            FROM line_items item, orders o
            WHERE item.order_id = o.id
                AND cust.current_order = o.id
        )

## 16.11. order by 節

クエリが返す list は、返されるクラスやコンポーネントの任意の属性によって並べ替えられます：

    from DomesticCat cat
    order by cat.name asc, cat.weight desc, cat.birthdate

オプションの `asc` と `desc` はそれぞれ昇順か降順の整列を示します。

## 16.12. group by 節

集約値を返すクエリは、返されるクラスやコンポーネントの任意のプロパティによってグループ化できます:

    select cat.color, sum(cat.weight), count(cat)
    from Cat cat
    group by cat.color

    select foo.id, avg(name), max(name)
    from Foo foo join foo.names name
    group by foo.id

`having` 節も使えます。

    select cat.color, sum(cat.weight), count(cat)
    from Cat cat
    group by cat.color
    having cat.color in (eg.Color.TABBY, eg.Color.BLACK)

もし使用するデータベースがサポートしているなら、 `having` と `order by` 節で SQL 関数と集約関数が使えます（例えば MySQL にはありません）。

    select cat
    from Cat cat
        join cat.kittens kitten
    group by cat.id, cat.name, cat.other, cat.properties
    having avg(kitten.weight)
    > 100
    order by count(kitten) asc, sum(kitten.weight) desc

`group by` 節や `order by` 節に算術式を含むことができないことに注意してください。また、 Hibernate は今のところグループエンティティを拡張しないことにも注意してください。したがって、もし `cat` の全てのプロパティが非集合体の場合、 `group by cat` を書くことはできません。全ての非集合体のプロパティを明示的にリストする必要があります。

## 16.13. 副問い合わせ

サブセレクトをサポートするデータベースのため、 Hibernate は副問い合わせをサポートしています。副問い合わせは括弧で囲まなければなりません（ SQL の集約関数呼び出しによる事が多いです）。関連副問い合わせ (外部クエリ中の別名を参照する副問い合わせのこと) さえ許可されます。

    from Cat as fatcat
    where fatcat.weight
    > (
        select avg(cat.weight) from DomesticCat cat
    )

    from DomesticCat as cat
    where cat.name = some (
        select name.nickName from Name as name
    )

    from Cat as cat
    where not exists (
        from Cat as mate where mate.mate = cat
    )

    from DomesticCat as cat
    where cat.name not in (
        select name.nickName from Name as name
    )

    select cat.id, (select max(kit.weight) from cat.kitten kit)
    from Cat as cat

HQL 副問い合わせは、 select または where 節だけで使われることに注意してください。

Note that subqueries can also utilize `row value constructor` syntax. See 「行値コンストラクタ構文」 for more information.

## 16.14. HQL の例

Hibernate クエリは非常に強力で複雑にできます。実際、クエリ言語の威力は Hibernate の主要なセールスポイントの一つです。ここに最近のプロジェクトで使用したクエリと非常によく似た例があります。ほとんどのクエリはこれらの例より簡単に記述できることに注意してください。

以下のクエリは特定の顧客と与えられた最小の合計値に対する未払い注文の注文 ID 、商品の数、注文の合計を合計値で整列して返します。価格を決定する際、現在のカタログを使います。結果として返される SQL クエリは `ORDER`、 `ORDER_LINE`、 `PRODUCT`、 `CATALOG` および `PRICE` テーブルに対し4つの内部結合と (関連しない) 副問い合わせを持ちます。

    select order.id, sum(price.amount), count(item)
    from Order as order
        join order.lineItems as item
        join item.product as product,
        Catalog as catalog
        join catalog.prices as price
    where order.paid = false
        and order.customer = :customer
        and price.product = product
        and catalog.effectiveDate < sysdate
        and catalog.effectiveDate
    >= all (
            select cat.effectiveDate
            from Catalog as cat
            where cat.effectiveDate < sysdate
        )
    group by order
    having sum(price.amount)
    > :minAmount
    order by sum(price.amount) desc

何て巨大なクエリなのでしょう。普段私は副問い合わせをあまり使いません。したがって私のクエリは実際には以下のようになります。:

    select order.id, sum(price.amount), count(item)
    from Order as order
        join order.lineItems as item
        join item.product as product,
        Catalog as catalog
        join catalog.prices as price
    where order.paid = false
        and order.customer = :customer
        and price.product = product
        and catalog = :currentCatalog
    group by order
    having sum(price.amount)
    > :minAmount
    order by sum(price.amount) desc

次のクエリは各ステータスの支払い数を数えます。ただしすべての支払いが現在の利用者による最新のステータス変更である `AWAITING_APPROVAL` である場合を除きます。このクエリは2つの内部結合と `PAYMENT`, `PAYMENT_STATUS` および `PAYMENT_STATUS_CHANGE` テーブルに対する関連副問い合わせを備えた SQL クエリに変換されます。

    select count(payment), status.name
    from Payment as payment
        join payment.currentStatus as status
        join payment.statusChanges as statusChange
    where payment.status.name <
    > PaymentStatus.AWAITING_APPROVAL
        or (
            statusChange.timeStamp = (
                select max(change.timeStamp)
                from PaymentStatusChange change
                where change.payment = payment
            )
            and statusChange.user <
    > :currentUser
        )
    group by status.name, status.sortOrder
    order by status.sortOrder

もし set の代わりに list として `statusChanges` コレクションをマッピングしたならば、はるかに簡単にクエリを記述できるでしょう。

    select count(payment), status.name
    from Payment as payment
        join payment.currentStatus as status
    where payment.status.name <
    > PaymentStatus.AWAITING_APPROVAL
        or payment.statusChanges[ maxIndex(payment.statusChanges) ].user <
    > :currentUser
    group by status.name, status.sortOrder
    order by status.sortOrder

次のクエリは現在のユーザーが所属する組織に対するアカウントおよび未払いの支払いをすべて返す MS SQL Server の `isNull()` 関数を使用しています。このクエリは3つの内部結合と1つの外部結合、そして `ACCOUNT`、 `PAYMENT`、 `PAYMENT_STATUS`、 `ACCOUNT_TYPE`、 `ORGANIZATION` および `ORG_USER` テーブルに対する副問い合わせ持った SQL に変換されます。

    select account, payment
    from Account as account
        left outer join account.payments as payment
    where :currentUser in elements(account.holder.users)
        and PaymentStatus.UNPAID = isNull(payment.currentStatus.name, PaymentStatus.UNPAID)
    order by account.type.sortOrder, account.accountNumber, payment.dueDate

いくつかのデータベースについては、 (関連させられた) 副問い合わせの使用を避ける必要があるでしょう。

    select account, payment
    from Account as account
        join account.holder.users as user
        left outer join account.payments as payment
    where :currentUser = user
        and PaymentStatus.UNPAID = isNull(payment.currentStatus.name, PaymentStatus.UNPAID)
    order by account.type.sortOrder, account.accountNumber, payment.dueDate

## 16.15. 大量の UPDATE と DELETE

HQL now supports `update`, `delete` and `insert ... select ...` statements. See 「DML スタイルの操作」 for more information.

## 16.16. Tips & Tricks

実際に結果を返さなくてもクエリの結果数を数えることができます:

    ( (Integer) session.createQuery("select count(*) from ....").iterate().next() ).intValue()

コレクションのサイズにより結果を並べ替えるためには以下のクエリを使用します:

    select usr.id, usr.name
    from User as usr
        left join usr.messages as msg
    group by usr.id, usr.name
    order by count(msg)

使用しているデータベースがサブセレクトをサポートする場合、クエリの where 節でサイズによる選択条件を設定できます:

    from User usr where size(usr.messages)
    >= 1

使用しているデータベースがサブセレクトをサポートしない場合は、次のクエリを使用してください:

    select usr.id, usr.name
    from User usr
        join usr.messages msg
    group by usr.id, usr.name
    having count(msg)
    >= 1

内部結合をしているせいで上の解決法が message の件数がゼロの `User` を返すことができないならば、以下の形式が使えます:

    select usr.id, usr.name
    from User as usr
        left join usr.messages as msg
    group by usr.id, usr.name
    having count(msg) = 0

JavaBean のプロパティは、名前付きのクエリパラメータに結びつけることが出来ます：

    Query q = s.createQuery("from foo Foo as foo where foo.name=:name and foo.size=:size");

    q.setProperties(fooBean); // fooBean has getName() and getSize()

    List foos = q.list();

コレクションはフィルタ付き `Query` インターフェースを使用することでページをつけることができます:

    Query q = s.createFilter( collection, "" ); // the trivial filter

    q.setMaxResults(PAGE_SIZE);

    q.setFirstResult(PAGE_SIZE * pageNumber);

    List page = q.list();

コレクションの要素はクエリフィルタを使って、並べ替えやグループ分けが出来ます:

    Collection orderedCollection = s.filter( collection, "order by this.amount" );

    Collection counts = s.filter( collection, "select this.type, count(this) group by this.type" );

コレクションを初期化せずにコレクションのサイズを得ることができます:

    ( (Integer) session.createQuery("select count(*) from ....").iterate().next() ).intValue();

## 16.17. コンポーネント

HQL クエリでシンプルな値型を使用できるので、コンポーネントは、あらゆる点で使用できます。これは `select` 節の中に現われます:

    select p.name from Person p

    select p.name.first from Person p

人名のプロパティがコンポーネントの場所。コンポーネントは、 `where` 節でも使用可能です:

    from Person p where p.name = :name

    from Person p where p.name.first = :firstName

コンポーネントは `order by` 節でも使用可能です:

    from Person p order by p.name

    from Person p order by p.name.first

Another common use of components is in row value constructors.

## 16.18. 行値コンストラクタ構文

下に位置するデータベースが ANSI SQL `row value constructor` 構文 (`tuple` 構文とよばれることもあります) をサポートしていないとしても、 HQL はその使用をサポートしています。ここでは、一般的にコンポーネントと連繋するマルチバリュー比較について触れます。ネームコンポーネントを定義する Person エンティティを考えましょう:

    from Person p where p.name.first='John' and p.name.last='Jingleheimer-Schmidt'

それは少々詳細になりますが、有効な構文です。より簡潔にし、 `row value constructor` 構文を使用するのがよいでしょう:

    from Person p where p.name=('John', 'Jingleheimer-Schmidt')

それを `select` 節で指定するのも効果的です。

    select p.name from Person p

次に `row value constructor` 構文の使用が有効なときは、サブクエリを使用して複数の値と比較する必要があるときです:

    from Cat as cat
    where not ( cat.name, cat.color ) in (
        select cat.name, cat.color from DomesticCat cat
    )

この構文を使用するかどうか決定するときに考慮しなければならないことは、クエリがメタデータ内のコンポーネントのサブプロパティの順番に依存していることです。

## 第17章 Criteria クエリ

Hibernate には、直感的で拡張可能な criteria クエリ API が用意されています。

## 17.1. `Criteria` インスタンスの作成

`org.hibernate.Criteria` インターフェースは特定の永続性クラスに対するクエリを表現します。 `Session` は `Criteria` インスタンスのファクトリです。

    Criteria crit = sess.createCriteria(Cat.class);

    crit.setMaxResults(50);

    List cats = crit.list();

## 17.2. リザルトセットの絞込み

`org.hibernate.criterion.Criterion` インターフェースのインスタンスは、個別のクエリクライテリオン（問い合わせの判定基準）を表します。 `org.hibernate.criterion.Restrictions` クラスは、ある組み込みの `Criterion` 型を取得するためのファクトリメソッドを持っています。

    List cats = sess.createCriteria(Cat.class)

        .add( Restrictions.like("name", "Fritz%") )

        .add( Restrictions.between("weight", minWeight, maxWeight) )

        .list();

Restriction （限定）は、論理的にグループ化できます。

    List cats = sess.createCriteria(Cat.class)

        .add( Restrictions.like("name", "Fritz%") )

        .add( Restrictions.or(

            Restrictions.eq( "age", new Integer(0) ),

            Restrictions.isNull("age")

        ) )

        .list();

    List cats = sess.createCriteria(Cat.class)

        .add( Restrictions.in( "name", new String[] { "Fritz", "Izi", "Pk" } ) )

        .add( Restrictions.disjunction()

            .add( Restrictions.isNull("age") )

            .add( Restrictions.eq("age", new Integer(0) ) )

            .add( Restrictions.eq("age", new Integer(1) ) )

            .add( Restrictions.eq("age", new Integer(2) ) )

        ) )

        .list();

元々ある Criterion 型（`Restrictions` のサブクラス） はかなりの範囲に及びますが、特に有用なのは SQL を直接指定できるものです。

    List cats = sess.createCriteria(Cat.class)

        .add( Restrictions.sqlRestriction("lower({alias}.name) like lower(?)", "Fritz%", Hibernate.STRING) )

        .list();

`{alias}` というプレースホルダは、問い合わせを受けたエンティティの行の別名によって置き換えられます。

criterion を得る別の手段は、 `Property` インスタンスから取得することです。 `Property.forName()` を呼び出して、 `Property` インスタンスを作成できます。

    Property age = Property.forName("age");

    List cats = sess.createCriteria(Cat.class)

        .add( Restrictions.disjunction()

            .add( age.isNull() )

            .add( age.eq( new Integer(0) ) )

            .add( age.eq( new Integer(1) ) )

            .add( age.eq( new Integer(2) ) )

        ) )

        .add( Property.forName("name").in( new String[] { "Fritz", "Izi", "Pk" } ) )

        .list();

## 17.3. 結果の整列

`org.hibernate.criterion.Order` を使って結果を並び替えることができます。

    List cats = sess.createCriteria(Cat.class)

        .add( Restrictions.like("name", "F%")

        .addOrder( Order.asc("name") )

        .addOrder( Order.desc("age") )

        .setMaxResults(50)

        .list();

    List cats = sess.createCriteria(Cat.class)

        .add( Property.forName("name").like("F%") )

        .addOrder( Property.forName("name").asc() )

        .addOrder( Property.forName("age").desc() )

        .setMaxResults(50)

        .list();

## 17.4. 関連

By navigating associations using `createCriteria()` you can specify constraints upon related entities:

    List cats = sess.createCriteria(Cat.class)

        .add( Restrictions.like("name", "F%") )

        .createCriteria("kittens")

            .add( Restrictions.like("name", "F%") )

        .list();

2番目の `createCriteria()` は、 `kittens` コレクションの要素を参照する新しい `Criteria` インスタンスを返すことに注意してください。

以下のような方法も、状況により有用です。

    List cats = sess.createCriteria(Cat.class)

        .createAlias("kittens", "kt")

        .createAlias("mate", "mt")

        .add( Restrictions.eqProperty("kt.name", "mt.name") )

        .list();

（`createAlias()` は新しい `Criteria` インスタンスを作成しません。）

前の2つのクエリによって返される `Cat` インスタンスによって保持される kittens コレクションは、 criteria によって事前にフィルタリング されない ことに注意してください。もし criteria に適合する kitten を取得したいなら、 `ResultTransformer` を使わなければなりません。

    List cats = sess.createCriteria(Cat.class)

        .createCriteria("kittens", "kt")

            .add( Restrictions.eq("name", "F%") )

        .setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP)

        .list();

    Iterator iter = cats.iterator();

    while ( iter.hasNext() ) {

        Map map = (Map) iter.next();

        Cat cat = (Cat) map.get(Criteria.ROOT_ALIAS);

        Cat kitten = (Cat) map.get("kt");

    }

Additionally you may manipulate the result set using a left outer join:

                    List cats = session.createCriteria( Cat.class )
                           .createAlias("mate", "mt", Criteria.LEFT_JOIN, Restrictions.like("mt.name", "good%") )
                           .addOrder(Order.asc("mt.age"))
                           .list();

This will return all of the `Cat`s with a mate whose name starts with "good" ordered by their mate's age, and all cats who do not have a mate. This is useful when there is a need to order or limit in the database prior to returning complex/large result sets, and removes many instances where multiple queries would have to be performed and the results unioned by java in memory.

Without this feature, first all of the cats without a mate would need to be loaded in one query.

A second query would need to retreive the cats with mates who's name started with "good" sorted by the mates age.

Thirdly, in memory; the lists would need to be joined manually.

## 17.5. 関連の動的フェッチ

`setFetchMode()` を使い、実行時に関連の復元方法を指定してもよいです。

    List cats = sess.createCriteria(Cat.class)

        .add( Restrictions.like("name", "Fritz%") )

        .setFetchMode("mate", FetchMode.EAGER)

        .setFetchMode("kittens", FetchMode.EAGER)

        .list();

This query will fetch both `mate` and `kittens` by outer join. See 「フェッチ戦略」 for more information.

## 17.6. クエリの例

`org.hibernate.criterion.Example` クラスは、与えられたインスタンスからクエリクライテリオンを構築できます。

    Cat cat = new Cat();

    cat.setSex('F');

    cat.setColor(Color.BLACK);

    List results = session.createCriteria(Cat.class)

        .add( Example.create(cat) )

        .list();

バージョンプロパティ、識別子、関連は無視されます。デフォルトでは null 値のプロパティは除外されます。

どのように `Example` を適用するか調整することができます。

    Example example = Example.create(cat)

        .excludeZeroes()           //exclude zero valued properties

        .excludeProperty("color")  //exclude the property named "color"

        .ignoreCase()              //perform case insensitive string comparisons

        .enableLike();             //use like for string comparisons

    List results = session.createCriteria(Cat.class)

        .add(example)

        .list();

関連オブジェクトに criteria を指定するために、 example を使うことも可能です。

    List results = session.createCriteria(Cat.class)

        .add( Example.create(cat) )

        .createCriteria("mate")

            .add( Example.create( cat.getMate() ) )

        .list();

## 17.7. 射影、集約、グループ化

`org.hibernate.criterion.Projections` クラスは `Projection` インスタンスのファクトリです。 `setProjection()` を呼び出すことで、クエリに射影を適用します。

    List results = session.createCriteria(Cat.class)

        .setProjection( Projections.rowCount() )

        .add( Restrictions.eq("color", Color.BLACK) )

        .list();

    List results = session.createCriteria(Cat.class)

        .setProjection( Projections.projectionList()

            .add( Projections.rowCount() )

            .add( Projections.avg("weight") )

            .add( Projections.max("weight") )

            .add( Projections.groupProperty("color") )

        )

        .list();

必要であっても、 criteria クエリに「group by」を明示する必要はありません。ある種の Projection 型は グループ化射影 として定義され、 SQL の `group by` 節にも現れます。

An alias can be assigned to a projection so that the projected value can be referred to in restrictions or orderings. Here are two different ways to do this:

    List results = session.createCriteria(Cat.class)

        .setProjection( Projections.alias( Projections.groupProperty("color"), "colr" ) )

        .addOrder( Order.asc("colr") )

        .list();

    List results = session.createCriteria(Cat.class)

        .setProjection( Projections.groupProperty("color").as("colr") )

        .addOrder( Order.asc("colr") )

        .list();

`alias()` と `as()` メソッドは、 Projection インスタンスを別の名前の `Projection` インスタンスでラップするだけです。ショートカットとして、射影を射影リストに追加する際に、別名をつけられます:

    List results = session.createCriteria(Cat.class)

        .setProjection( Projections.projectionList()

            .add( Projections.rowCount(), "catCountByColor" )

            .add( Projections.avg("weight"), "avgWeight" )

            .add( Projections.max("weight"), "maxWeight" )

            .add( Projections.groupProperty("color"), "color" )

        )

        .addOrder( Order.desc("catCountByColor") )

        .addOrder( Order.desc("avgWeight") )

        .list();

    List results = session.createCriteria(Domestic.class, "cat")

        .createAlias("kittens", "kit")

        .setProjection( Projections.projectionList()

            .add( Projections.property("cat.name"), "catName" )

            .add( Projections.property("kit.name"), "kitName" )

        )

        .addOrder( Order.asc("catName") )

        .addOrder( Order.asc("kitName") )

        .list();

射影の式に `Property.forName()` も使用できます:

    List results = session.createCriteria(Cat.class)

        .setProjection( Property.forName("name") )

        .add( Property.forName("color").eq(Color.BLACK) )

        .list();

    List results = session.createCriteria(Cat.class)

        .setProjection( Projections.projectionList()

            .add( Projections.rowCount().as("catCountByColor") )

            .add( Property.forName("weight").avg().as("avgWeight") )

            .add( Property.forName("weight").max().as("maxWeight") )

            .add( Property.forName("color").group().as("color" )

        )

        .addOrder( Order.desc("catCountByColor") )

        .addOrder( Order.desc("avgWeight") )

        .list();

## 17.8. クエリおよびサブクエリの分離

`DetachedCriteria` クラスにより、セッションスコープ外にクエリを作成できます。後で、任意の `Session` を使って、実行できます。

    DetachedCriteria query = DetachedCriteria.forClass(Cat.class)

        .add( Property.forName("sex").eq('F') );

    Session session = ....;

    Transaction txn = session.beginTransaction();

    List results = query.getExecutableCriteria(session).setMaxResults(100).list();

    txn.commit();

    session.close();

`DetachedCriteria` は、サブクエリを表現するためにも使えます。サブクエリを伴う Criterion インスタンスは、 `Subqueries` もしくは `Property` から得られます。

    DetachedCriteria avgWeight = DetachedCriteria.forClass(Cat.class)

        .setProjection( Property.forName("weight").avg() );

    session.createCriteria(Cat.class)

        .add( Property.forName("weight").gt(avgWeight) )

        .list();

    DetachedCriteria weights = DetachedCriteria.forClass(Cat.class)

        .setProjection( Property.forName("weight") );

    session.createCriteria(Cat.class)

        .add( Subqueries.geAll("weight", weights) )

        .list();

相互関係があるサブクエリでさえも可能です:

    DetachedCriteria avgWeightForSex = DetachedCriteria.forClass(Cat.class, "cat2")

        .setProjection( Property.forName("weight").avg() )

        .add( Property.forName("cat2.sex").eqProperty("cat.sex") );

    session.createCriteria(Cat.class, "cat")

        .add( Property.forName("weight").gt(avgWeightForSex) )

        .list();

## 17.9. 自然識別子によるクエリ

criteria クエリを含むたいていのクエリにとって、クエリキャッシュはあまり効率がよくないです。なぜなら、クエリキャッシュが頻繁に無効になるためです。しかしながら、キャッシュを無効にするアルゴリズムを最適化できる特別なクエリの種類が１つあります。更新されない自然キーによる検索です。いくつかのアプリケーションでは、この種類のクエリが頻繁に現れます。このような使われ方のために、 criteria API は特別な対策を提供します。

最初に、 `<natural-id>` を使って、エンティティの自然キーをマップしてください。そして、二次キャッシュを有効にします。

    <class name="User">

        <cache usage="read-write"/>

        <id name="id">

            <generator class="increment"/>

        </id>

        <natural-id>

            <property name="name"/>

            <property name="org"/>

        </natural-id>

        <property name="password"/>

    </class

    >

注記： 変更される 自然キーを持つエンティティにこの機能を使うのは、意図されていない使い方です。

これで、 `Restrictions.naturalId()` により、より効率的なキャッシュアルゴリズムを使用できます。

    session.createCriteria(User.class)

        .add( Restrictions.naturalId()

            .set("name", "gavin")

            .set("org", "hb")

        ).setCacheable(true)

        .uniqueResult();

## 第18章 ネイティブ SQL

データベースのネイティブ SQL 方言を使ってクエリを表現することもできます。クエリヒントや Oracle の `CONNECT` キーワードのように、データベース独自の機能を利用したいときに使えます。 SQL/JDBC を直接使用しているアプリケーションから Hibernate への移行も容易にしています。

Hibernate3 では、生成、更新、削除、読み込み処理のようなすべての SQL （ストアドプロシージャを含む）を手書きできます。

## 18.1. Using a `SQLQuery`

ネイティブな SQL クエリの実行は `SQLQuery` インターフェースを通して制御します。 `SQLQuery` インターフェースは `Session.createSQLQuery()` を呼び出して取得します。この API を使って問い合わせする方法を以下で説明します。

### 18.1.1. スカラーのクエリ

最も基本的な SQL クエリはスカラー（値）のリストを得ることです。

    sess.createSQLQuery("SELECT * FROM CATS").list();

    sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").list();

これらはどちらも、 CATS テーブルの各カラムのスカラー値を含む Object 配列（Object[]）のリストを返します。返すスカラー値の実際の順番と型を推定するために、 Hibernate は ResultSetMetadata を使用します。

`ResultSetMetadata` を使用するオーバーヘッドを避けるため、もしくは単に何が返されるか明確にするため、 `addScalar()` を使えます。

    sess.createSQLQuery("SELECT * FROM CATS")

     .addScalar("ID", Hibernate.LONG)

     .addScalar("NAME", Hibernate.STRING)

     .addScalar("BIRTHDATE", Hibernate.DATE)

このクエリで指定されているものを下記に示します:

- SQL クエリ文字列

- 返されるカラムと型

これはまだ Object 配列を返しますが、 `ResultSetMetdata` を使用しません。ただし、その代わりに基礎にあるリザルトセットから ID、NAME、BIRTHDATE カラムをそれぞれ Long、String、Short として明示的に取得します。これは３つのカラムを返すのみであることも意味します。たとえ、クエリが `*` を使用し、列挙した３つより多くのカラムを返せるとしてもです。

スカラーの型情報を省くこともできます。

    sess.createSQLQuery("SELECT * FROM CATS")

     .addScalar("ID", Hibernate.LONG)

     .addScalar("NAME")

     .addScalar("BIRTHDATE")

これは本質的に前と同じクエリですが、 NAME と BIRTHDATE の型を決めるために `ResultSetMetaData` を使用します。一方、 ID の型は明示的に指定されています。

ResultSetMetaData から返される java.sql.Types を Hibernate の型に マッピングすることは、 Dialect が制御します。明示された型がマッピングされていないか、結果の型が期待したものと異なる場合、 Dialect の `registerHibernateType` を呼び出し、カスタマイズできます。

### 18.1.2. エンティティのクエリ

ここまでのクエリは、すべてスカラー値を返すものでした。基本的に、リザルトセットから「未加工」の値を返します。以降では、 `addEntity()` により、ネイティブ SQL クエリからエンティティオブジェクトを取得する方法を示します。

    sess.createSQLQuery("SELECT * FROM CATS").addEntity(Cat.class);

    sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").addEntity(Cat.class);

このクエリで指定されているものを下記に示します:

- SQL クエリ文字列

- クエリが返すエンティティと SQL テーブルの別名

Cat が ID 、 NAME 、 BIRTHDATE のカラムを使ってクラスにマッピングされる場合、上記のクエリはどちらも、要素が Cat エンティティであるリストを返します。

エンティティを別のエンティティに `多対一` でマッピングしている場合は、ネイティブクエリを実行する際に、この別のエンティティを返すことも要求します。さもなければ、データベース固有の「column not found(カラムが見つかりません)」エラーが発生します。 * 表記を使用した際は、追加のカラムが自動的に返されますが、次の例のように、 `Dog` に `多対一` であることを明示することを私たちは好みます。

    sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE, DOG_ID FROM CATS").addEntity(Cat.class);

これにより cat.getDog() が正しく機能します。

### 18.1.3. 関連とコレクションの操作

プロキシを初期化するための余分な処理を避けるため、 `Dog` の中で即時結合できます。これは `addJoin()` メソッドにより行います。関連もしくはコレクションに結合できます。

    sess.createSQLQuery("SELECT c.ID, NAME, BIRTHDATE, DOG_ID, D_ID, D_NAME FROM CATS c, DOGS d WHERE c.DOG_ID = d.D_ID")

     .addEntity("cat", Cat.class)

     .addJoin("cat.dog");

この例の中で、返される `Cat` は、データベースへの余分処理なしで、完全に初期化された `dog` プロパティを持ちます。結合対象のプロパティへのパスを指定できるように、別名（「cat」）を追加したことに注意してください。コレクションの即時結合も同じようにできます。たとえば、 `Cat` が一対多で `Dog` を持っていた場合、次のようになります。

    sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE, D_ID, D_NAME, CAT_ID FROM CATS c, DOGS d WHERE c.ID = d.CAT_ID")

     .addEntity("cat", Cat.class)

     .addJoin("cat.dogs");

現在のところ、 Hibernate で使いやすくするための SQL クエリの拡張なしに、ネイティブクエリで何かを可能にする限界に来ています。同じ型のエンティティを複数返す際や、デフォルトの別名や列名で十分ではない場合に、問題は起こり始めます。

### 18.1.4. 複数エンティティの取得

ここまでは、リザルトセットのカラム名は、マッピングドキュメントで指定されたカラム名と同じであると仮定していました。複数のテーブルが同じカラム名を持つ場合があるため、複数テーブルを結合する SQL クエリで問題となる場合があります。

下記のような（失敗しそうな）クエリでは、カラム別名インジェクション（column alias injection）が必要です：

    sess.createSQLQuery("SELECT c.*, m.*  FROM CATS c, CATS m WHERE c.MOTHER_ID = m.ID")

     .addEntity("cat", Cat.class)

     .addEntity("mother", Cat.class)

このクエリの意図は、１行ごとに２つの Cat インスタンス、つまり猫とその母親を返すということです。同じカラム名にマッピングすることにより名前が衝突するため、このクエリは失敗します。ベータベースによっては、返されるカラムの別名が "c.ID"、"c.NAME" などの形式であり、マッピングで指定されたカラム（"ID" と "NAME"）と等しくないため、失敗します。

下記の形式は、カラム名が重複しても大丈夫です：

    sess.createSQLQuery("SELECT {cat.*}, {m.*}  FROM CATS c, CATS m WHERE c.MOTHER_ID = m.ID")

     .addEntity("cat", Cat.class)

     .addEntity("mother", Cat.class)

このクエリで指定されているものを下記に示します:

- SQL クエリ文字列 （Hibernate がカラムの別名を挿入するためのプレースホルダを含む）

- クエリによって返されるエンティティ

上記で使用している {cat.*} と {mother.*} という表記は、「すべてのプロパティ」を表す省略形です。代わりに、明示的にカラムを列挙してもよいですが、その場合は、 Hibernate に各プロパティに対応する SQL カラムの別名を挿入させるべきでしょう。カラムの別名のためのプレースホルダは、テーブルの別名によって修飾されたプロパティ名です。下記の例では、別のテーブル cat_log から マッピングメタデータで定義された Cat とその母親を復元します。もし好むなら、 where 節の中でも、プロパティの別名を使えます。

    String sql = "SELECT ID as {c.id}, NAME as {c.name}, " +

             "BIRTHDATE as {c.birthDate}, MOTHER_ID as {c.mother}, {mother.*} " +

             "FROM CAT_LOG c, CAT_LOG m WHERE {c.mother} = c.ID";

    List loggedCats = sess.createSQLQuery(sql)

            .addEntity("cat", Cat.class)

            .addEntity("mother", Cat.class).list()

#### 18.1.4.1. 別名とプロパティのリファレンス

多くの場合、上記のような別名インジェクションが必要です。ただし、複合プロパティ、継承識別子、コレクションなどのようなより複雑なマッピングと関連するクエリがなければです。ある特定の別名を使用することにより、 Hibernate は適切な別名を挿入できます。

別名インジェクションとして使用できるものを下表に示します。注記：下表の別名は一例です。それぞれの別名は一意であり、使用する際にはおそらく異なる名前を持ちます。

表18.1 別名に挿入する名前

説明 | 構文 | 例
--- | --- | ---
単純なプロパティ | `{[aliasname].[propertyname]` | `A_NAME as {item.name}`
複合プロパティ | `{[aliasname].[componentname].[propertyname]}` | `CURRENCY as {item.amount.currency}, VALUE as {item.amount.value}`
エンティティのクラスを識別する値 | `{[aliasname].class}` | `DISC as {item.class}`
エンティティの全プロパティ | `{[aliasname].*}` | `{item.*}`
コレクションのキー | `{[aliasname].key}` | `ORGID as {coll.key}`
コレクションの ID | `{[aliasname].id}` | `EMPID as {coll.id}`
コレクションの要素 | `{[aliasname].element}` | `XID as {coll.element}`
コレクションの要素のプロパティ | `{[aliasname].element.[propertyname]}` | `NAME as {coll.element.name}`
コレクションの要素の全プロパティ | `{[aliasname].element.*}` | `{coll.element.*}`
All properties of the collection | `{[aliasname].*}` | `{coll.*}`

### 18.1.5. 管理されていないエンティティの取得

ネイティブ SQL クエリに ResultTransformer を適用できます。下記のように、例えば、管理されていないエンティティを返します。

    sess.createSQLQuery("SELECT NAME, BIRTHDATE FROM CATS")

            .setResultTransformer(Transformers.aliasToBean(CatDTO.class))

このクエリで指定されているものを下記に示します:

- SQL クエリ文字列

- 結果を変換したもの

上記のクエリは、インスタンス化し、 NAME と BIRTHDATE の値を対応するプロパティもしくはフィールドに挿入した `CatDTO` のリストを返します。

### 18.1.6. 継承の制御

継承の一部としてマッピングされたエンティティを問い合わせるネイティブ SQL クエリは、ベースのクラスとそのすべてのサブクラスのプロパティすべてを含まなければなりません。

### 18.1.7. パラメータ

ネイティブ SQL クエリは、以下のように、名前付きパラメータ（:name）と同様に位置パラメータをサポートします:

    Query query = sess.createSQLQuery("SELECT * FROM CATS WHERE NAME like ?").addEntity(Cat.class);

    List pusList = query.setString(0, "Pus%").list();

    query = sess.createSQLQuery("SELECT * FROM CATS WHERE NAME like :name").addEntity(Cat.class);

    List pusList = query.setString("name", "Pus%").list();

## 18.2. 名前付き SQL クエリ

Named SQL queries can also be defined in the mapping document and called in exactly the same way as a named HQL query (see 「名前付きクエリの外出し」). In this case, you do not need to call `addEntity()`.

例18.1 Named sql query using the <sql-query> maping element

    <sql-query name="persons">

        <return alias="person" class="eg.Person"/>

        SELECT person.NAME AS {person.name},

               person.AGE AS {person.age},

               person.SEX AS {person.sex}

        FROM PERSON person

        WHERE person.NAME LIKE :namePattern

    </sql-query>

例18.2 Execution of a named query

    List people = sess.getNamedQuery("persons")

        .setString("namePattern", namePattern)

        .setMaxResults(50)

        .list();

The `<return-join>` element is use to join associations and the `<load-collection>` element is used to define queries which initialize collections,

例18.3 Named sql query with association

    <sql-query name="personsWith">

        <return alias="person" class="eg.Person"/>

        <return-join alias="address" property="person.mailingAddress"/>

        SELECT person.NAME AS {person.name},

               person.AGE AS {person.age},

               person.SEX AS {person.sex},

               address.STREET AS {address.street},

               address.CITY AS {address.city},

               address.STATE AS {address.state},

               address.ZIP AS {address.zip}

        FROM PERSON person

        JOIN ADDRESS address

            ON person.ID = address.PERSON_ID AND address.TYPE='MAILING'

        WHERE person.NAME LIKE :namePattern

    </sql-query>

名前付き SQL クエリはスカラ値を返すこともできます。 `<return-scalar>` 要素を使って、列の別名と Hibernate の型を宣言しなければなりません:

例18.4 Named query returning a scalar

    <sql-query name="mySqlQuery">

        <return-scalar column="name" type="string"/>

        <return-scalar column="age" type="long"/>

        SELECT p.NAME AS name,

               p.AGE AS age,

        FROM PERSON p WHERE p.NAME LIKE 'Hiber%'

    </sql-query>

リザルトセットのマッピング情報を `<resultset>` に外部化することができます。複数の名前付きクエリで再利用したり、 `setResultSetMapping()` API を通して再利用したりできます。

例18.5 <resultset> mapping used to externalize mapping information

    <resultset name="personAddress">

        <return alias="person" class="eg.Person"/>

        <return-join alias="address" property="person.mailingAddress"/>

    </resultset>

    <sql-query name="personsWith" resultset-ref="personAddress">

        SELECT person.NAME AS {person.name},

               person.AGE AS {person.age},

               person.SEX AS {person.sex},

               address.STREET AS {address.street},

               address.CITY AS {address.city},

               address.STATE AS {address.state},

               address.ZIP AS {address.zip}

        FROM PERSON person

        JOIN ADDRESS address

            ON person.ID = address.PERSON_ID AND address.TYPE='MAILING'

        WHERE person.NAME LIKE :namePattern

    </sql-query>

代わりに、 hbm ファイル内のリザルトセットのマッピング情報を直接 Java コードの中で使用できます。

例18.6 Programmatically specifying the result mapping information

    List cats = sess.createSQLQuery(

            "select {cat.*}, {kitten.*} from cats cat, cats kitten where kitten.mother = cat.id"

        )

        .setResultSetMapping("catAndKitten")

        .list();

So far we have only looked at externalizing SQL queries using Hibernate mapping files. The same concept is also available with anntations and is called named native queries. You can use `@NamedNativeQuery` (`@NamedNativeQueries`) in conjunction with `@SqlResultSetMapping` (`@SqlResultSetMappings`). Like `@NamedQuery`, `@NamedNativeQuery` and `@SqlResultSetMapping` can be defined at class level, but their scope is global to the application. Lets look at a view examples.

例18.7「Named SQL query using @NamedNativeQuery together with @SqlResultSetMapping」 shows how a `resultSetMapping` parameter is defined in `@NamedNativeQuery`. It represents the name of a defined `@SqlResultSetMapping`. The resultset mapping declares the entities retrieved by this native query. Each field of the entity is bound to an SQL alias (or column name). All fields of the entity including the ones of subclasses and the foreign key columns of related entities have to be present in the SQL query. Field definitions are optional provided that they map to the same column name as the one declared on the class property. In the example 2 entities, `Night` and `Area`, are returned and each property is declared and associated to a column name, actually the column name retrieved by the query.

In 例18.8「Implicit result set mapping」 the result set mapping is implicit. We only describe the entity class of the result set mapping. The property / column mappings is done using the entity mapping values. In this case the model property is bound to the model_txt column.

Finally, if the association to a related entity involve a composite primary key, a `@FieldResult` element should be used for each foreign key column. The `@FieldResult` name is composed of the property name for the relationship, followed by a dot ("."), followed by the name or the field or property of the primary key. This can be seen in 例18.9「Using dot notation in @FieldResult for specifying associations 」.

例18.7 Named SQL query using `@NamedNativeQuery` together with `@SqlResultSetMapping`

    @NamedNativeQuery(name="night&area", query="select night.id nid, night.night_duration, "

        + " night.night_date, area.id aid, night.area_id, area.name "

        + "from Night night, Area area where night.area_id = area.id",

                      resultSetMapping="joinMapping")

    @SqlResultSetMapping(name="joinMapping", entities={

        @EntityResult(entityClass=Night.class, fields = {

            @FieldResult(name="id", column="nid"),

            @FieldResult(name="duration", column="night_duration"),

            @FieldResult(name="date", column="night_date"),

            @FieldResult(name="area", column="area_id"),

            discriminatorColumn="disc"

        }),

        @EntityResult(entityClass=org.hibernate.test.annotations.query.Area.class, fields = {

            @FieldResult(name="id", column="aid"),

            @FieldResult(name="name", column="name")

        })

        }

    )

例18.8 Implicit result set mapping

    @Entity

    @SqlResultSetMapping(name="implicit",

                         entities=@EntityResult(entityClass=SpaceShip.class))

    @NamedNativeQuery(name="implicitSample",

                      query="select * from SpaceShip",

                      resultSetMapping="implicit")

    public class SpaceShip {

        private String name;

        private String model;

        private double speed;

        @Id

        public String getName() {

            return name;

        }

        public void setName(String name) {

            this.name = name;

        }

        @Column(name="model_txt")

        public String getModel() {

            return model;

        }

        public void setModel(String model) {

            this.model = model;

        }

        public double getSpeed() {

            return speed;

        }

        public void setSpeed(double speed) {

            this.speed = speed;

        }

    }

例18.9 Using dot notation in @FieldResult for specifying associations

    @Entity

    @SqlResultSetMapping(name="compositekey",

            entities=@EntityResult(entityClass=SpaceShip.class,

                fields = {

                        @FieldResult(name="name", column = "name"),

                        @FieldResult(name="model", column = "model"),

                        @FieldResult(name="speed", column = "speed"),

                        @FieldResult(name="captain.firstname", column = "firstn"),

                        @FieldResult(name="captain.lastname", column = "lastn"),

                        @FieldResult(name="dimensions.length", column = "length"),

                        @FieldResult(name="dimensions.width", column = "width")

                        }),

            columns = { @ColumnResult(name = "surface"),

                        @ColumnResult(name = "volume") } )

    @NamedNativeQuery(name="compositekey",

        query="select name, model, speed, lname as lastn, fname as firstn, length, width, length * width as surface from SpaceShip",

        resultSetMapping="compositekey")

    } )

    public class SpaceShip {

        private String name;

        private String model;

        private double speed;

        private Captain captain;

        private Dimensions dimensions;

        @Id

        public String getName() {

            return name;

        }

        public void setName(String name) {

            this.name = name;

        }

        @ManyToOne(fetch= FetchType.LAZY)

        @JoinColumns( {

                @JoinColumn(name="fname", referencedColumnName = "firstname"),

                @JoinColumn(name="lname", referencedColumnName = "lastname")

                } )

        public Captain getCaptain() {

            return captain;

        }

        public void setCaptain(Captain captain) {

            this.captain = captain;

        }

        public String getModel() {

            return model;

        }

        public void setModel(String model) {

            this.model = model;

        }

        public double getSpeed() {

            return speed;

        }

        public void setSpeed(double speed) {

            this.speed = speed;

        }

        public Dimensions getDimensions() {

            return dimensions;

        }

        public void setDimensions(Dimensions dimensions) {

            this.dimensions = dimensions;

        }

    }

    @Entity

    @IdClass(Identity.class)

    public class Captain implements Serializable {

        private String firstname;

        private String lastname;

        @Id

        public String getFirstname() {

            return firstname;

        }

        public void setFirstname(String firstname) {

            this.firstname = firstname;

        }

        @Id

        public String getLastname() {

            return lastname;

        }

        public void setLastname(String lastname) {

            this.lastname = lastname;

        }

    }

## ティップ

If you retrieve a single entity using the default mapping, you can specify the `resultClass` attribute instead of `resultSetMapping`:

    @NamedNativeQuery(name="implicitSample", query="select * from SpaceShip", resultClass=SpaceShip.class)

    public class SpaceShip {

In some of your native queries, you'll have to return scalar values, for example when building report queries. You can map them in the `@SqlResultsetMapping` through `@ColumnResult`. You actually can even mix, entities and scalar returns in the same native query (this is probably not that common though).

例18.10 Scalar values via `@ColumnResult`

    @SqlResultSetMapping(name="scalar", columns=@ColumnResult(name="dimension"))

    @NamedNativeQuery(name="scalar", query="select length*width as dimension from SpaceShip", resultSetMapping="scalar")

An other query hint specific to native queries has been introduced: `org.hibernate.callable` which can be true or false depending on whether the query is a stored procedure or not.

### 18.2.1. 列と列の別名を明示的に指定するために return-property を使う

別名を挿入するために `{}` 構文を使う代わりに、 `<return-property>` を使い、どの列の別名を使うのかを明示できます。

    <sql-query name="mySqlQuery">

        <return alias="person" class="eg.Person">

            <return-property name="name" column="myName"/>

            <return-property name="age" column="myAge"/>

            <return-property name="sex" column="mySex"/>

        </return>

        SELECT person.NAME AS myName,

               person.AGE AS myAge,

               person.SEX AS mySex,

        FROM PERSON person WHERE person.NAME LIKE :name

    </sql-query>

`<return-property>` は複数の列も扱えます。これは、複数列のプロパティをきめ細かく制御できないという、 `{}` 構文の制限を解決します。

    <sql-query name="organizationCurrentEmployments">

        <return alias="emp" class="Employment">

            <return-property name="salary">

                <return-column name="VALUE"/>

                <return-column name="CURRENCY"/>

            </return-property>

            <return-property name="endDate" column="myEndDate"/>

        </return>

            SELECT EMPLOYEE AS {emp.employee}, EMPLOYER AS {emp.employer},

            STARTDATE AS {emp.startDate}, ENDDATE AS {emp.endDate},

            REGIONCODE as {emp.regionCode}, EID AS {emp.id}, VALUE, CURRENCY

            FROM EMPLOYMENT

            WHERE EMPLOYER = :id AND ENDDATE IS NULL

            ORDER BY STARTDATE ASC

    </sql-query>

この例では、挿入のための `{}` 構文といっしょに、 `<return-property>` を使っていることに注意してください。列とプロパティをどのように参照するかを選べます。

マッピングに discriminator が含まれている場合、 discriminator の列を指定するために、 `<return-discriminator>` を使わなければなりません。

### 18.2.2. 問い合わせするためにストアドプロシージャを使う

Hibernate はバージョン3から、ストアドプロシージャとストアド関数経由の問い合わせがサポートされました。以降の文書の多くは、両方に当てはまります。ストアドプロシージャやストアド関数を Hibernate で使うためには、1番目の出力パラメータとしてリザルトセットを返さなければなりません。 Oracle 9（もしくはそれ以上のバージョン）のストアドプロシージャの例を以下に示します:

    CREATE OR REPLACE FUNCTION selectAllEmployments

        RETURN SYS_REFCURSOR

    AS

        st_cursor SYS_REFCURSOR;

    BEGIN

        OPEN st_cursor FOR

     SELECT EMPLOYEE, EMPLOYER,

     STARTDATE, ENDDATE,

     REGIONCODE, EID, VALUE, CURRENCY

     FROM EMPLOYMENT;

          RETURN  st_cursor;

     END;

Hibernate でこのクエリを使うためには、名前付きクエリでマッピングする必要があります。

    <sql-query name="selectAllEmployees_SP" callable="true">

        <return alias="emp" class="Employment">

            <return-property name="employee" column="EMPLOYEE"/>

            <return-property name="employer" column="EMPLOYER"/>

            <return-property name="startDate" column="STARTDATE"/>

            <return-property name="endDate" column="ENDDATE"/>

            <return-property name="regionCode" column="REGIONCODE"/>

            <return-property name="id" column="EID"/>

            <return-property name="salary">

                <return-column name="VALUE"/>

                <return-column name="CURRENCY"/>

            </return-property>

        </return>

        { ? = call selectAllEmployments() }

    </sql-query>

注記：今のところ、ストアドプロシージャはスカラとエンティティを返すのみです。 `<return-join>` と `<load-collection>` はサポートされていません。

#### 18.2.2.1. ストアドプロシージャを使う上でのルールと制限

Hibernate でストアドプロシージャや関数を使うためには、そのプロシージャはいくつかのルールに準拠する必要があります。ルールに準拠していないプロシージャは、 Hibernate で使うことはできません。それでも、準拠していないプロシージャを使いたいのであれば、 `session.connection()` を通じて実行しなければなりません。ルールはデータベースごとに異なります。ストアドプロシージャのセマンティックスとシンタックスは、データベースベンダごとに異なるためです。

`setFirstResult()/setMaxResults()` を使って、ストアドプロシージャクエリをページ分けすることはできません。

推奨する呼び出し方は、標準である SQL92 に従うことです。 `{ ? = call functionName(<parameters>) }` や `{ ? = call procedureName(<parameters>}` です。ネイティブな呼び出し構文はサポートされていません。

Oracle には下記のルールが適用されます:

- 関数はリザルトセットを返さなければなりません。プロシージャの第一引数はリザルトセットを返すため、 `OUT` でなければなりません。 Oracle 9 と 10 では、 `SYS_REFCURSOR` を使うことによってできます。 Oracle では `REF CURSOR` 型を定義する必要があります。 Oracle の文献を参照してください。

Sybase と MS SQL サーバーに適用されるルールを下記に示します:

- プロシージャはリザルトセットを返さなければなりません。サーバーは複数のリザルトセットと更新カウントを返しますが、 Hibernate は1つ目のリザルトセットだけを返すことに注意してください。その他はすべて捨てられます。

- プロシージャの中で `SET NOCOUNT ON` を有効にできれば、おそらく効率がよくなるでしょう。しかし、これは必要条件ではありません。

## 18.3. 作成、更新、削除のためのカスタム SQL

Hibernate3 can use custom SQL for create, update, and delete operations. The SQL can be overridden at the statement level or inidividual column level. This section describes statement overrides. For columns, see 「Column transformers: read and write expressions」. 例18.11「Custom CRUD via annotations」 shows how to define custom SQL operatons using annotations.

例18.11 Custom CRUD via annotations

    @Entity

    @Table(name="CHAOS")

    @SQLInsert( sql="INSERT INTO CHAOS(size, name, nickname, id) VALUES(?,upper(?),?,?)")

    @SQLUpdate( sql="UPDATE CHAOS SET size = ?, name = upper(?), nickname = ? WHERE id = ?")

    @SQLDelete( sql="DELETE CHAOS WHERE id = ?")

    @SQLDeleteAll( sql="DELETE CHAOS")

    @Loader(namedQuery = "chaos")

    @NamedNativeQuery(name="chaos", query="select id, size, name, lower( nickname ) as nickname from CHAOS where id= ?", resultClass = Chaos.class)

    public class Chaos {

        @Id

        private Long id;

        private Long size;

        private String name;

        private String nickname;

`@SQLInsert`, `@SQLUpdate`, `@SQLDelete`, `@SQLDeleteAll` respectively override the INSERT, UPDATE, DELETE, and DELETE all statement. The same can be achieved using Hibernate mapping files and the `<sql-insert>`, `<sql-update>` and `<sql-delete>` nodes. This can be seen in 例18.12「Custom CRUD XML」.

例18.12 Custom CRUD XML

    <class name="Person">

        <id name="id">

            <generator class="increment"/>

        </id>

        <property name="name" not-null="true"/>

        <sql-insert>INSERT INTO PERSON (NAME, ID) VALUES ( UPPER(?), ? )</sql-insert>

        <sql-update>UPDATE PERSON SET NAME=UPPER(?) WHERE ID=?</sql-update>

        <sql-delete>DELETE FROM PERSON WHERE ID=?</sql-delete>

    </class>

If you expect to call a store procedure, be sure to set the `callable` attribute to `true`. In annotations as well as in xml.

To check that the execution happens correctly, Hibernate allows you to define one of those three strategies:

- none: no check is performed: the store procedure is expected to fail upon issues

- count: use of rowcount to check that the update is successful

- param: like COUNT but using an output parameter rather that the standard mechanism

To define the result check style, use the `check` parameter which is again available in annoations as well as in xml.

You can use the exact same set of annotations respectively xml nodes to override the collection related statements -see 例18.13「Overriding SQL statements for collections using annotations」.

例18.13 Overriding SQL statements for collections using annotations

    @OneToMany

    @JoinColumn(name="chaos_fk")

    @SQLInsert( sql="UPDATE CASIMIR_PARTICULE SET chaos_fk = ? where id = ?")

    @SQLDelete( sql="UPDATE CASIMIR_PARTICULE SET chaos_fk = null where id = ?")

    private Set<CasimirParticle> particles = new HashSet<CasimirParticle>();

## ティップ

The parameter order is important and is defined by the order Hibernate handles properties. You can see the expected order by enabling debug logging for the `org.hibernate.persister.entity` level. With this level enabled Hibernate will print out the static SQL that is used to create, update, delete etc. entities. (To see the expected sequence, remember to not include your custom SQL through annotations or mapping files as that will override the Hibernate generated static sql)

Overriding SQL statements for secondary tables is also possible using `@org.hibernate.annotations.Table` and either (or all) attributes `sqlInsert`, `sqlUpdate`, `sqlDelete`:

例18.14 Overriding SQL statements for secondary tables

    @Entity

    @SecondaryTables({

        @SecondaryTable(name = "`Cat nbr1`"),

        @SecondaryTable(name = "Cat2"})

    @org.hibernate.annotations.Tables( {

        @Table(appliesTo = "Cat", comment = "My cat table" ),

        @Table(appliesTo = "Cat2", foreignKey = @ForeignKey(name="FK_CAT2_CAT"), fetch = FetchMode.SELECT,

            sqlInsert=@SQLInsert(sql="insert into Cat2(storyPart2, id) values(upper(?), ?)") )

    } )

    public class Cat implements Serializable {

The previous example also shows that you can give a comment to a given table (primary or secondary): This comment will be used for DDL generation.

## ティップ

The SQL is directly executed in your database, so you can use any dialect you like. This will, however, reduce the portability of your mapping if you use database specific SQL.

Last but not least, stored procedures are in most cases required to return the number of rows inserted, updated and deleted. Hibernate always registers the first statement parameter as a numeric output parameter for the CUD operations:

例18.15 Stored procedures and their return value

    CREATE OR REPLACE FUNCTION updatePerson (uid IN NUMBER, uname IN VARCHAR2)
        RETURN NUMBER IS
    BEGIN

        update PERSON
        set
            NAME = uname,
        where
            ID = uid;

        return SQL%ROWCOUNT;

    END updatePerson;

## 18.4. ロードのためのカスタム SQL

You can also declare your own SQL (or HQL) queries for entity loading. As with inserts, updates, and deletes, this can be done at the individual column level as described in 「Column transformers: read and write expressions」 or at the statement level. Here is an example of a statement level override:

    <sql-query name="person">

        <return alias="pers" class="Person" lock-mode="upgrade"/>

        SELECT NAME AS {pers.name}, ID AS {pers.id}

        FROM PERSON

        WHERE ID=?

        FOR UPDATE

    </sql-query>

これは、まさに（以前議論した）名前付きクエリの宣言です。この名前付きクエリをクラスのマッピングから参照できます:

    <class name="Person">

        <id name="id">

            <generator class="increment"/>

        </id>

        <property name="name" not-null="true"/>

        <loader query-ref="person"/>

    </class>

これはストアドプロシージャでさえも動作します。

次のように、コレクションをロードするためのクエリさえ定義してよいです:

    <set name="employments" inverse="true">

        <key/>

        <one-to-many class="Employment"/>

        <loader query-ref="employments"/>

    </set>

    <sql-query name="employments">

        <load-collection alias="emp" role="Person.employments"/>

        SELECT {emp.*}

        FROM EMPLOYMENT emp

        WHERE EMPLOYER = :id

        ORDER BY STARTDATE ASC, EMPLOYEE ASC

    </sql-query>

次のように、結合フェッチによりコレクションをロードするエンティティローダーを定義できます:

    <sql-query name="person">

        <return alias="pers" class="Person"/>

        <return-join alias="emp" property="pers.employments"/>

        SELECT NAME AS {pers.*}, {emp.*}

        FROM PERSON pers

        LEFT OUTER JOIN EMPLOYMENT emp

            ON pers.ID = emp.PERSON_ID

        WHERE ID=?

    </sql-query>

The annotation equivalent `<loader>` is the @Loader annotation as seen in 例18.11「Custom CRUD via annotations」.

## 第19章 データのフィルタリング

Hibernate3 では「可視性」ルールに基づいてデータを扱うための画期的な方法を用意しています。 Hibernate filter はグローバルで、名前付きで、パラメータ化されたフィルタです。これは Hibernate セッションごとに有効無効を切り替えられます。

## 19.1. Hibernate のフィルタ

Hibernate3 はフィルタクライテリアをあらかじめ定義し、これらのフィルタをクラスやコレクションレベルに加える機能を加えました。フィルタクライテリアは制約節を定義する機能です。これらのフィルタ条件はパラメータ化できるということを除き、クラスやさまざまなコレクション要素で利用可能な ｢where｣ 句に非常によく似ています。アプリケーションは、与えられたフィルタを可能にすべきか、そしてそのパラメータ値を何にすべきかを実行時に決定することができます。フィルタはデータベースビューのように使用されますが、アプリケーション内ではパラメータ化されます。

Using annotatons filters are defined via `@org.hibernate.annotations.FilterDef` or `@org.hibernate.annotations.FilterDefs`. A filter definition has a `name()` and an array of parameters(). A parameter will allow you to adjust the behavior of the filter at runtime. Each parameter is defined by a `@ParamDef` which has a name and a type. You can also define a `defaultCondition()` parameter for a given `@FilterDef` to set the default condition to use when none are defined in each individual `@Filter`. `@FilterDef`(s) can be defined at the class or package level.

We now need to define the SQL filter clause applied to either the entity load or the collection load. `@Filter` is used and placed either on the entity or the collection element. The connection between `@FilterName` and `@Filter` is a matching name.

例19.1 @FilterDef and @Filter annotations

    @Entity

    @FilterDef(name="minLength", parameters=@ParamDef( name="minLength", type="integer" ) )

    @Filters( {

        @Filter(name="betweenLength", condition=":minLength <= length and :maxLength >= length"),

        @Filter(name="minLength", condition=":minLength <= length")

    } )

    public class Forest { ... }

When the collection use an association table as a relational representation, you might want to apply the filter condition to the association table itself or to the target entity table. To apply the constraint on the target entity, use the regular `@Filter` annotation. However, if you want to target the association table, use the `@FilterJoinTable` annotation.

例19.2 Using `@FilterJoinTable` for filterting on the association table

    @OneToMany

        @JoinTable

        //filter on the target entity table

        @Filter(name="betweenLength", condition=":minLength <= length and :maxLength >= length")

        //filter on the association table

        @FilterJoinTable(name="security", condition=":userlevel >= requredLevel")

        public Set<Forest> getForests() { ... }

Using Hibernate mapping files for defining filters the situtation is very similar. The filters must first be defined and then attached to the appropriate mapping elements. To define a filter, use the `<filter-def/>` element within a `<hibernate-mapping/>` element:

例19.3 Defining a filter definition via `<filter-def>`

    <filter-def name="myFilter">

        <filter-param name="myFilterParam" type="string"/>

    </filter-def>

This filter can then be attached to a class or collection (or, to both or multiples of each at the same time):

例19.4 Attaching a filter to a class or collection using `<filter>`

    <class name="myClass" ...>

        ...

        <filter name="myFilter" condition=":myFilterParam = MY_FILTERED_COLUMN"/>

        <set ...>

            <filter name="myFilter" condition=":myFilterParam = MY_FILTERED_COLUMN"/>

        </set>

    </class>

`Session` 上のメソッドは `enableFilter(String filterName)`、 `getEnabledFilter(String filterName)`、 `disableFilter(String filterName)` です。デフォルトでは、フィルタは与えられたセッションに対して使用 できません 。 `Filter` インスタンスを返り値とする `Session.enabledFilter()` メソッドを使うことで、フィルタは明示的に使用可能となります。上で定義した単純なフィルタの使用は、このようになります：

    session.enableFilter("myFilter").setParameter("myFilterParam", "some-value");

org.hibernate.Filter インターフェースのメソッドは、 Hibernate の多くに共通しているメソッド連鎖を許していることに注意してください。

有効なレコードデータパターンを持つ一時データを使った完全な例です：

    <filter-def name="effectiveDate">

        <filter-param name="asOfDate" type="date"/>

    </filter-def>

    <class name="Employee" ...>

    ...

        <many-to-one name="department" column="dept_id" class="Department"/>

        <property name="effectiveStartDate" type="date" column="eff_start_dt"/>

        <property name="effectiveEndDate" type="date" column="eff_end_dt"/>

    ...

        <!--

            Note that this assumes non-terminal records have an eff_end_dt set to

            a max db date for simplicity-sake

        -->

        <filter name="effectiveDate"

                condition=":asOfDate BETWEEN eff_start_dt and eff_end_dt"/>

    </class>

    <class name="Department" ...>

    ...

        <set name="employees" lazy="true">

            <key column="dept_id"/>

            <one-to-many class="Employee"/>

            <filter name="effectiveDate"

                    condition=":asOfDate BETWEEN eff_start_dt and eff_end_dt"/>

        </set>

    </class>

常に現在の有効レコードを返却することを保証するために、単純に、社員データの検索より前にセッション上のフィルタを有効にします:

    Session session = ...;

    session.enableFilter("effectiveDate").setParameter("asOfDate", new Date());

    List results = session.createQuery("from Employee as e where e.salary > :targetSalary")

             .setLong("targetSalary", new Long(1000000))

             .list();

上記の HQL では、結果の給料の制約について明示的に触れただけですが、有効になっているフィルタのおかげで、このクエリは給料が100万ドル以上の現役の社員だけを返します。

注記： (HQL かロードフェッチで）外部結合を持つフィルタを使うつもりなら、条件式の方向に注意してください。これは左外部結合のために設定するのが最も安全です。一般的に、演算子の後カラム名に続けて最初のパラメータを配置してください。

定義したあと、フィルタは、それぞれ独自のコンディションを持つ複数のエンティティやコレクションにアタッチされます。コンディションがいつも同じ場合、それは面倒かもしれません。従って、 `<filter-def/>` は、属性または CDATA としてデフォルトコンディションを定義することが可能になります：

    <filter-def name="myFilter" condition="abc > xyz">...</filter-def>

    <filter-def name="myOtherFilter">abc=xyz</filter-def>

このデフォルトのコンディションは、コンディションを指定せずに何かにアタッチされる場合いつでも使われます。これは、特定のケースにおいてデフォルトのコンディションをオーバーライドするフィルターのアタッチメントの一部として、特定のコンディションを与えることができることを意味します。

## 第20章 XML マッピング

XML Mapping is an experimental feature in Hibernate 3.0 and is currently under active development.

## 20.1. XML データでの作業

Hibernate では永続性の POJO を使って作業するのとほぼ同じようなやり方で、永続性の XML データを使って作業できます。解析された XML ツリーは POJO の代わりにオブジェクトレベルで関係データを表わす別の方法であるとみなされています。

Hibernate は XML ツリーを操作するための API として dom4j をサポートしています。データベースから dom4j のツリーを復元するクエリを書くことができ、ツリーに対して行った修正は自動的にデータベースと同期されます。また XML ドキュメントを取得することができ、 dom4j を使ってドキュメントをパースし、 Hibernate の任意の基本操作を使ってデータベースへ書き込むことができます。： つまり、 `persist(), saveOrUpdate(), merge(), delete(), replicate()` 操作です (マージはまだサポートしていません)。

データのインポート/エクスポート、 JMS によるエンティティデータの外部化や SOAP 、 XSLT ベースのレポートなど、この機能には多くの用途があります。

単一のマッピングは、クラスのプロパティと XML ドキュメントのノードを同時にデータベースへマッピングするために使うことができます。またマッピングするクラスがなければ、 XML だけをマッピングするために使うことができます。

### 20.1.1. XML とクラスのマッピングを同時に指定する

これは POJO と XML を同時にマッピングする例です：

    <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

    >

### 20.1.2. XML マッピングだけを指定する

これは POJO クラスがないマッピングの例です：

    <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

    >

このマッピングにより、 dom4j ツリーか、プロパティ名/値の組のグラフ（java の `Map`）としてデータにアクセスできます。プロパティの名前は、 HQL クエリ内で参照できる純粋な論理構造です。

## 20.2. XML マッピングのメタデータ

多くの Hibernate のマッピング要素は `node` 属性が使用できます。これにより XML 属性の名前やプロパティやエンティティデータを保持する要素を指定できます。 `node` 属性のフォーマットは以下の中の1つでなければなりません：

- `"element-name"` - 指定した XML 要素へマッピングします

- `"@attribute-name"` - 指定した XML 属性へマッピングします

- `"."` - 親要素へマッピングします

- `"element-name/@attribute-name"` - 指定したエレメントの指定した属性へマッピングします

コレクションと単一の値の関連に対して、おまけの `embed-xml` 属性があります。デフォルトの `embed-xml="true"` と設定した場合、関連するエンティティ (値型のコレクション) の XML ツリーは、直接関連を所有するエンティティの XML ツリー内に埋め込まれます。反対に、 `embed-xml="false"` と設定した場合、参照される識別子の値だけが多重度１側の関連に対する XML に現れ、単純にコレクションはまったく現れなくなります。

あまりに多くの関連に対して `embed-xml="true"` としたままにするのは注意すべきです。 XML は循環をうまく扱えません。

    <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

    >

この例では、実際の account のデータではなく、 account の id のコレクションを埋め込むことにしました。続きの HQL クエリです：

    from Customer c left join fetch c.accounts where c.lastName like :lastName

このようなデータセットを返すでしょう:

    <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

    >

`<one-to-many>` マッピングで `embed-xml="true"` と設定した場合、データはこのようになるでしょう。

    <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

    >

## 20.3. XML データを扱う

XML ドキュメントを、アプリケーション内で再読み込みや更新をしてみましょう。以下では dom4j のセッションを取得することで行います：

    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();

    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();

XML ベースのデータのインポート/エクスポートを実装するために、 Hibernate の `replicate()` 操作をこの機能に結びつけるのは極めて有効です。

## 第21章 パフォーマンスの改善

## 21.1. フェッチ戦略

フェッチ戦略 は、アプリケーションが関連をナビゲートする必要があるときに、 Hibernate が関連オブジェクトを復元するために使用する戦略です。フェッチ戦略は O/R マッピングのメタデータに宣言するか、特定の HQL 、 `Criteria` クエリでオーバーライドします。

Hibernate3 は次に示すフェッチ戦略を定義しています:

- 結合フェッチ - Hibernate は `OUTER JOIN` を使って、関連するインスタンスやコレクションを１つの `SELECT` で復元します。

- セレクトフェッチ - 2回目の `SELECT` で関連するエンティティやコレクションを復元します。 `lazy="false"` で明示的に遅延フェッチを無効にしなければ、この2回目の select は実際に関連にアクセスしたときのみ実行されるでしょう。

- サブセレクトフェッチ - 2回目の `SELECT` で、直前のクエリやフェッチで復元したすべての要素に関連するコレクションを復元します。 `lazy="false"` で明示的に遅延フェッチを無効にしなければ、この2回目の select は実際に関連にアクセスしたときのみ実行されるでしょう。

- バッチフェッチ - セレクトフェッチのための最適化された戦略 - Hibernate はエンティティのインスタンスやコレクションの一群を1回の `SELECT` で復元します。これは主キーや外部キーのリストを指定することにより行います。

Hibernate は次に示す戦略とも区別をします:

- 即時フェッチ - 所有者のオブジェクトがロードされたときに、関連、コレクションは即時にフェッチされます。

- 遅延コレクションフェッチ - アプリケーションがコレクションに対して操作を行ったときにコレクションをフェッチします。(これはコレクションに対するデフォルトの動作です)

- 「特別な遅延」コレクションフェッチ - コレクションの要素１つ１つが独立して、必要なときにデータベースから取得されます。 Hibernate は必要ないならば、コレクション全体をメモリにフェッチすることは避けます（とても大きなコレクションに適しています）。

- プロキシフェッチ - 単一値関連は、識別子の getter 以外のメソッドが関連オブジェクトで呼び出されるときにフェッチされます。

- 「プロキシなし」フェッチ - 単一値関連は、インスタンス変数にアクセスされたときにフェッチされます。プロキシフェッチと比較すると、この方法は遅延の度合いが少ない（関連は識別子にアクセスしただけでもフェッチされます）ですが、より透過的で、アプリケーションにプロキシが存在しないように見せます。この方法はビルド時のバイトコード組み込みが必要になり、使う場面はまれです。

- 遅延属性フェッチ - 属性や単一値関連は、インスタンス変数にアクセスしたときにフェッチされます。この方法はビルド時のバイトコード組み込みが必要になり、使う場面はまれです。

二つの直行する概念があります: いつ 関連をフェッチするか、そして、 どうやって フェッチするか（どんな SQL を使って）。これらを混同しないでください。 `fetch` はパフォーマンスチューニングに使います。 `lazy` はあるクラスの分離されたインスタンスのうち、どのデータを常に使用可能にするかの取り決めを定義します。

### 21.1.1. 遅延関連の働き

デフォルトでは、 Hibernate3 はコレクションに対しては遅延セレクトフェッチを使い、単一値関連には遅延プロキシフェッチを使います。これらのデフォルト動作はほぼすべてのアプリケーションのほぼすべての関連で意味があります。

注:`hibernate.default_batch_fetch_size` をセットしたときは、 Hibernate は遅延フェッチのためのバッチフェッチ最適化を使うでしょう（この最適化はより細かいレベルで有効にすることも出来ます）。

しかし、遅延フェッチは知っておかなければならない一つの問題があります。 Hibernate の session をオープンしているコンテキストの外から遅延関連にアクセスすると、例外が発生します。例：

    s = sessions.openSession();

    Transaction tx = s.beginTransaction();

    User u = (User) s.createQuery("from User u where u.name=:userName")

        .setString("userName", userName).uniqueResult();

    Map permissions = u.getPermissions();

    tx.commit();

    s.close();

    Integer accessLevel = (Integer) permissions.get("accounts");  // Error!

`Session` がクローズされたとき、 permissions コレクションは初期化されていないため、このコレクションは自身の状態をロードできません。 Hibernate は切り離されたオブジェクトの遅延初期化はサポートしていません 。修正方法として、コレクションから読み込みを行うコードをトランザクションをコミットする直前に移動させます。

一方で、 `lazy="false"` を関連マッピングに指定することで、遅延処理をしないコレクションや関連を使うことが出来ます。しかしながら、遅延初期化はほぼすべてのコレクションや関連で使われることを意図しています。もしあなたのオブジェクトモデルの中に遅延処理をしない関連を多く定義してしまうと、 Hibernate は最終的にはトランザクション毎にほぼ完全なデータベースをメモリの中にフェッチすることになるでしょう。

他方では、特定のトランザクションにおいてセレクトフェッチの代わりに結合フェッチ（当然これは遅延処理ではなくなります）を選択したいことが時々あります。これからフェッチ戦略をカスタマイズする方法をお見せします。 Hibernate3 では、フェッチ戦略を選択する仕組みは単一値関連とコレクションで変わりはありません。

### 21.1.2. フェッチ戦略のチューニング

セレクトフェッチ（デフォルト）は N+1 セレクト問題という大きな弱点があるため、マッピング定義で結合フェッチを有効にすることができます:

    <set name="permissions"

                fetch="join">

        <key column="userId"/>

        <one-to-many class="Permission"/>

    </set

    <many-to-one name="mother" class="Cat" fetch="join"/>

マッピング定義で定義した `フェッチ` 戦略は次のものに影響します:

- `get()` や `load()` による復元

- 関連にナビゲートしたときに発生する暗黙的な復元

- `Criteria` クエリ

- `サブセレクト` フェッチを使う HQL クエリ

たとえどんなフェッチ戦略を使ったとしても、遅延ではないグラフはメモリに読み込まれることが保証されます。つまり、特定の HQL クエリを実行するためにいくつかの SELECT 文が即時実行されることがあるので注意してください。

通常は、マッピング定義でフェッチのカスタマイズは行いません。代わりに、デフォルトの動作のままにしておいて、 HQL で `left join fetch` を指定することで特定のトランザクションで動作をオーバーライドします。これは Hibernate に初回のセレクトで外部結合を使って関連を先にフェッチするように指定しています。 `Criteria` クエリの API では、 `setFetchMode(FetchMode.JOIN)` を使うことが出来ます。

もし `get()` や `load()` で使われるフェッチ戦略を変えたいと感じたときには、単純に `Criteria` クエリを使ってください。例：

    User user = (User) session.createCriteria(User.class)

                    .setFetchMode("permissions", FetchMode.JOIN)

                    .add( Restrictions.idEq(userId) )

                    .uniqueResult();

（これはいくつかの ORM ソリューションが "fetch plan" と呼んでいるものと同じです。）

N+1 セレクト問題を避けるためのまったく違う方法は、第2レベルキャッシュを使うことです。

### 21.1.3. 単一端関連プロキシ

コレクションの遅延フェッチは、 Hibernate 自身の実装による永続コレクションを使って実現しています。しかし、単一端関連における遅延処理では、違う仕組みが必要です。対象の関連エンティティはプロキシでなければなりません。 Hibernate は（すばらしい CGLIB ライブラリによる）実行時のバイトコード拡張を使って永続オブジェクトの遅延初期化プロキシを実現しています。

デフォルトでは、 Hibernate3 は（開始時に）すべての永続クラスのプロキシを生成し、それらを使って、 `many-to-one` や `one-to-one` 関連の遅延フェッチを可能にしています。

マッピングファイルで `proxy` 属性によって、クラスのプロキシインターフェースとして使うインターフェースを宣言できます。デフォルトでは、 Hibernate はそのクラスのサブクラスを使います。 プロキシクラスは少なくともパッケージ可視でデフォルトコンストラクタを実装しなければならないことに注意してください。すべての永続クラスにこのコンストラクタを推奨します。

ポリモーフィズムのクラスに対してこの方法を適用するときにいくつか考慮することがあります。例：

    <class name="Cat" proxy="Cat">

        ......

        <subclass name="DomesticCat">

            .....

        </subclass>

    </class>

第一に、 `Cat` のインスタンスは `DomesticCat` にキャストできません。たとえ基となるインスタンスが `DomesticCat` であったとしてもです:

    Cat cat = (Cat) session.load(Cat.class, id);  // instantiate a proxy (does not hit the db)

    if ( cat.isDomesticCat() ) {                  // hit the db to initialize the proxy

        DomesticCat dc = (DomesticCat) cat;       // Error!

        ....

    }

第二に、プロキシの `==` は成立しないことがあります。

    Cat cat = (Cat) session.load(Cat.class, id);            // instantiate a Cat proxy

    DomesticCat dc =

            (DomesticCat) session.load(DomesticCat.class, id);  // acquire new DomesticCat proxy!

    System.out.println(cat==dc);                            // false

しかし、これは見かけほど悪い状況というわけではありません。たとえ異なったプロキシオブジェクトへの二つの参照があったとしても、基となるインスタンスは同じオブジェクトです:

    cat.setWeight(11.0);  // hit the db to initialize the proxy

    System.out.println( dc.getWeight() );  // 11.0

第三に、 `final` クラスや `final` メソッドを持つクラスに CGLIB プロキシを使えません。

最後に、もし永続オブジェクトのインスタンス化時 (例えば、初期化処理やデフォルトコンストラクタの中で) になんらかのリソースが必要となるなら、そのリソースもまたプロキシを通して取得されます。実際には、プロキシクラスは永続クラスのサブクラスです。

これらの問題は Java の単一継承モデルの原理上の制限のためです。もしこれらの問題を避けたいのなら、ビジネスメソッドを宣言したインターフェースをそれぞれ永続クラスで実装しなければなりません。マッピングファイルでこれらのインターフェースを指定する必要があります。例：

    <class name="CatImpl" proxy="Cat">

        ......

        <subclass name="DomesticCatImpl" proxy="DomesticCat">

            .....

        </subclass>

    </class>

Then proxies for instances of `Cat` and `DomesticCat` can be returned by `load()` or `iterate()`.

    Cat cat = (Cat) session.load(CatImpl.class, catid);

    Iterator iter = session.createQuery("from CatImpl as cat where cat.name='fritz'").iterate();

    Cat fritz = (Cat) iter.next();

## Note

`list()` does not usually return proxies.

関連も遅延初期化されます。これはプロパティを `Cat` 型で宣言しなければならないことを意味します。 `CatImpl` ではありません。

プロキシの初期化を 必要としない 操作も存在します。

- `equals()` （永続クラスが `equals()` をオーバーライドしないとき）

- `hashCode()` （永続クラスが `hashCode()` をオーバーライドしないとき）

- 識別子の getter メソッド

Hibernate は `equals()` や `hashCode()` をオーバーライドした永続クラスを検出します。

デフォルトの `lazy="proxy"` の代わりに、 `lazy="no-proxy"` を選んだことで、型変換に関連する問題を回避することが出来ます。しかし、ビルド時のバイトコード組み込みが必要になり、どのような操作であっても、ただちにプロキシの初期化を行うことになるでしょう。

### 21.1.4. コレクションとプロキシの初期化

`LazyInitializationException` は、 `Session` のスコープ外から初期化していないコレクションやプロキシにアクセスされたときに、 Hibernate によってスローされます。すなわち、コレクションやプロキシへの参照を持つエンティティが分離された状態の時です。

`Session` をクローズする前にプロキシやコレクションの初期化を確実に行いたいときがあります。もちろん、 `cat.getSex()` や `cat.getKittens().size()` などを常に呼び出すことで初期化を強制することはできます。しかしこれはコードを読む人を混乱させ、汎用的なコードという点からも不便です。

static メソッドの `Hibernate.initialize()` や `Hibernate.isInitialized()` は遅延初期化のコレクションやプロキシを扱うときに便利な方法をアプリケーションに提供します。 `Hibernate.initialize(cat)` は、 `Session` がオープンしている限りは `cat` プロキシを強制的に初期化します。 `Hibernate.initialize( cat.getKittens() )` は kittens コレクションに対して同様の効果があります。

別の選択肢として、必要なすべてのコレクションやプロキシがロードされるまで `Session` をオープンにしておく方法があります。いくつかのアプリケーションのアーキテクチャでは、特に Hibernate によるデータアクセスを行うコードと、それを使うコードが異なるアプリケーションのレイヤーや、物理的に異なるプロセッサのときには、コレクションが初期化されるときに `Session` がオープンしていることを保証する問題があります。この問題に対しては2つの基本的な方法があります:

- Web ベースのアプリケーションでは、ビューのレンダリングが完了し、リクエストが終わる一番最後で `Session` をクローズするために、サーブレットフィルタを使うことができます（ Open Session in View パターンです）。もちろん、アプリケーション基盤の例外処理の正確性が非常に重要になります。ビューのレンダリング中に例外が発生したときでさえ、ユーザーに処理が戻る前に `Session` のクローズとトランザクションの終了を行うことが不可欠になります。 Hibernate の Wiki に載っている "Open Session in View" パターンの例を参照してください。

- ビジネス層が分離しているアプリケーションでは、ビジネスロジックは Web 層で必要になるすべてのコレクションを事前に「準備」する必要があります。これは特定のユースケースで必要となるプレゼンテーション/ Web 層に対し、ビジネス層がすべてのデータをロードし、すべてのデータを初期化して返すべきということを意味しています。通常は、アプリケーションは Web 層で必要なコレクションそれぞれに対して `Hibernate.initialize()` を呼び出すか（この呼び出しはセッションをクローズする前に行う必要があります）、 Hibernate クエリの `FETCH` 節や `Criteria` の `FetchMode.JOIN` を使ってコレクションを先に復元します。普通は Session Facade パターンの代わりに Command パターンを採用するほうがより簡単です。

- 初期化されていないコレクション（もしくは他のプロキシ）にアクセスする前に、 `merge()` や `lock()` を使って新しい `Session` に以前にロードされたオブジェクトを追加することも出来ます。アドホックなトランザクションのセマンティクスを導入したので、 Hibernate はこれを自動的に行わず、 行うべきでもありません 。

大きなコレクションを初期化したくはないが、コレクションについてのなんらかの情報（サイズのような）やデータのサブセットを必要とすることがあります。

コレクションフィルタを使うことで、初期化せずにコレクションのサイズを取得することが出来ます：

    ( (Integer) s.createFilter( collection, "select count(*)" ).list().get(0) ).intValue()

`createFilter()` メソッドは、コレクション全体を初期化する必要なしに、コレクションのサブセットを復元するために効果的に使えます:

    s.createFilter( lazyCollection, "").setFirstResult(0).setMaxResults(10).list();

### 21.1.5. バッチフェッチの使用

Hibernate はバッチフェッチを効率的に使用できます。一つのプロキシ（もしくはコレクション）がアクセスされると、 Hibernate はいくつかの初期化していないプロキシをロードすることができます。バッチフェッチは遅延セレクトフェッチ戦略に対する最適化です。バッチフェッチの調整には２つの方法があります。クラスレベルとコレクションレベルです。

クラス、要素のバッチフェッチは理解が簡単です。実行時の次の場面を想像してください。 `Session` にロードされた25個の `Cat` インスタンスが存在し、それぞれの `Cat` は `owner` である `Person` への関連を持ちます。 `Person` クラスは `lazy="true"` のプロキシでマッピングされています。もし今すべての Cat に対して繰り返し `getOwner()` を呼び出すと、 Hibernate はデフォルトでは25回の `SELECT` を実し、 owner プロキシの復元をします。この振る舞いを `Person` のマッピングの `batch-size` の指定で調整できます。

    <class name="Person" batch-size="10">...</class>

Hibernate はクエリを３回だけを実行するようになります。パターンは 10, 10, 5 です。

コレクションのバッチフェッチも有効にすることが出来ます。例として、それぞれの `Person` が `Cat` の遅延コレクションを持っており、 10 個の Person が `Sesssion` にロードされたとすると、すべての Person に対して繰り返し `getCats()` を呼び出すことで、計10回の `SELECT` が発生します。もし `Person` のマッピングで `cats` コレクションのバッチフェッチを有効にすれば、 Hibernate はコレクションの事前フェッチが出来ます。

    <class name="Person">

        <set name="cats" batch-size="3">

            ...

        </set>

    </class>

`batch-size` が 3 なので、 Hibernate は 4 回の `SELECT` で 3 個、 3 個、 3 個、 1 個をロードします。繰り返すと、属性の値は特定の `Session` の中の初期化されていないコレクションの期待数に依存します。

コレクションのバッチフェッチはアイテムのネストしたツリー、すなわち、代表的な部品表のパターンがある場合に特に有用です。（しかし、読み込みが多いツリーでは ネストした set や 具体化したパス がよりよい選択になります。）

### 21.1.6. サブセレクトフェッチの使用

一つの遅延コレクションや単一値プロキシがフェッチされなければいけないとき、 Hibernate はそれらすべてをロードし、サブセレクトのオリジナルクエリが再度実行されます。これはバッチフェッチと同じ方法で動き、少しずつのロードは行いません。

### 21.1.7. Fetch profiles

Another way to affect the fetching strategy for loading associated objects is through something called a fetch profile, which is a named configuration associated with the `org.hibernate.SessionFactory` but enabled, by name, on the `org.hibernate.Session`. Once enabled on a `org.hibernate.Session`, the fetch profile will be in affect for that `org.hibernate.Session` until it is explicitly disabled.

So what does that mean? Well lets explain that by way of an example which show the different available approaches to configure a fetch profile:

例21.1 Specifying a fetch profile using `@FetchProfile`

    @Entity

    @FetchProfile(name = "customer-with-orders", fetchOverrides = {

       @FetchProfile.FetchOverride(entity = Customer.class, association = "orders", mode = FetchMode.JOIN)

    })

    public class Customer {

       @Id

       @GeneratedValue

       private long id;

       private String name;

       private long customerNumber;

       @OneToMany

       private Set<Order> orders;

       // standard getter/setter

       ...

    }

例21.2 Specifying a fetch profile using `<fetch-profile>` outside `<class>` node

    <hibernate-mapping>

        <class name="Customer">

            ...

            <set name="orders" inverse="true">

                <key column="cust_id"/>

                <one-to-many class="Order"/>

            </set>

        </class>

        <class name="Order">

            ...

        </class>

        <fetch-profile name="customer-with-orders">

            <fetch entity="Customer" association="orders" style="join"/>

        </fetch-profile>

    </hibernate-mapping>

例21.3 Specifying a fetch profile using `<fetch-profile>` inside `<class>` node

    <hibernate-mapping>

        <class name="Customer">

            ...

            <set name="orders" inverse="true">

                <key column="cust_id"/>

                <one-to-many class="Order"/>

            </set>

            <fetch-profile name="customer-with-orders">

                <fetch association="orders" style="join"/>

            </fetch-profile>

        </class>

        <class name="Order">

            ...

        </class>

    </hibernate-mapping>

Now normally when you get a reference to a particular customer, that customer's set of orders will be lazy meaning we will not yet have loaded those orders from the database. Normally this is a good thing. Now lets say that you have a certain use case where it is more efficient to load the customer and their orders together. One way certainly is to use "dynamic fetching" strategies via an HQL or criteria queries. But another option is to use a fetch profile to achieve that. The following code will load both the customer andtheir orders:

例21.4 Activating a fetch profile for a given `Session`

    Session session = ...;

    session.enableFetchProfile( "customer-with-orders" );  // name matches from mapping

    Customer customer = (Customer) session.get( Customer.class, customerId );

## 注意

`@FetchProfile` definitions are global and it does not matter on which class you place them. You can place the `@FetchProfile` annotation either onto a class or package (package-info.java). In order to define multiple fetch profiles for the same class or package `@FetchProfiles` can be used.

Currently only join style fetch profiles are supported, but they plan is to support additional styles. See HHH-3414 for details.

### 21.1.8. 遅延プロパティフェッチの使用

Hibernate3 はプロパティごとの遅延フェッチをサポートしています。この最適化手法は グループのフェッチ としても知られています。これはほとんど要望から出た機能であることに注意してください。実際には列読み込みの最適化よりも、行読み込みの最適化が非常に重要です。しかし、クラスのいくつかのプロパティだけを読み込むことは、既存のテーブルが何百もの列を持ち、データモデルを改善できないなどの極端な場合には有用です。

遅延プロパティ読み込みを有効にするには、対象のプロパティのマッピングで `lazy` 属性をセットしてください:

    <class name="Document">

           <id name="id">

            <generator class="native"/>

        </id>

        <property name="name" not-null="true" length="50"/>

        <property name="summary" not-null="true" length="200" lazy="true"/>

        <property name="text" not-null="true" length="2000" lazy="true"/>

    </class>

遅延プロパティ読み込みはビルド時のバイトコード組み込みを必要とします。もし永続クラスに組み込みがされていないなら、 Hibernate は黙って遅延プロパティの設定を無視して、即時フェッチに戻します。

バイトコード組み込みは以下の Ant タスクを使ってください:

    <target name="instrument" depends="compile">

        <taskdef name="instrument" classname="org.hibernate.tool.instrument.InstrumentTask">

            <classpath path="${jar.path}"/>

            <classpath path="${classes.dir}"/>

            <classpath refid="lib.class.path"/>

        </taskdef>

        <instrument verbose="true">

            <fileset dir="${testclasses.dir}/org/hibernate/auction/model">

                <include name="*.class"/>

            </fileset>

        </instrument>

    </target>

不要な列を読み込まないための、別の（よりよい？）方法は、少なくとも読み込みのみのトランザクションにおいては、 HQL や Criteria クエリの射影機能を使うことです。この方法はビルド時のバイトコード組み込みが不要になり、より良い解決方法です。

HQL で `fetch all properties` を使うことで、普通どおりのプロパティの即時フェッチングを強制することが出来ます。

## 21.2. 第2レベルキャッシュ

Hibernate の `Session` は永続データのトランザクションレベルのキャッシュです。 class-by-class と collection-by-collection ごとの、クラスタレベルや JVM レベル （ `SessionFactory` レベル）のキャッシュを設定することが出来ます。クラスタ化されたキャッシュにつなぐことさえ出来ます。しかし注意してください。キャッシュは他のアプリケーションによる永続層の変更を考慮しません（キャッシュデータを定期的に期限切れにする設定は出来ます）。

You have the option to tell Hibernate which caching implementation to use by specifying the name of a class that implements `org.hibernate.cache.CacheProvider` using the property `hibernate.cache.provider_class`. Hibernate is bundled with a number of built-in integrations with the open-source cache providers that are listed in 表21.1「キャッシュプロバイダ」. You can also implement your own and plug it in as outlined above. Note that versions prior to Hibernate 3.2 use EhCache as the default cache provider.

表21.1 キャッシュプロバイダ

キャッシュ | プロバイダクラス | タイプ | クラスタセーフ | クエリキャッシュのサポート
--- | --- | --- | --- | ---
Hashtable（製品用として意図していません） | `org.hibernate.cache.HashtableCacheProvider` | メモリ |  | yes
EHCache | `org.hibernate.cache.EhCacheProvider` | memory, disk, transactional, clustered | yes | yes
OSCache | `org.hibernate.cache.OSCacheProvider` | メモリ、ディスク |  | yes
SwarmCache | `org.hibernate.cache.SwarmCacheProvider` | クラスタ（ip マルチキャスト） | yes（クラスタ無効化） |
JBoss Cache 1.x | `org.hibernate.cache.TreeCacheProvider` | クラスタ（ip マルチキャスト）、トランザクショナル | yes（複製） | yes（時刻同期が必要）
JBoss Cache 2 | `org.hibernate.cache.jbc.JBossCacheRegionFactory` | クラスタ（ip マルチキャスト）、トランザクショナル | yes (replication or invalidation) | yes（時刻同期が必要）

### 21.2.1. キャッシュのマッピング

As we have done in previous chapters we are looking at the two different possibiltites to configure caching. First configuration via annotations and then via Hibernate mapping files.

By default, entities are not part of the second level cache and we recommend you to stick to this setting. However, you can override this by setting the `shared-cache-mode` element in your `persistence.xml` file or by using the `javax.persistence.sharedCache.mode` property in your configuration. The following values are possible:

- `ENABLE_SELECTIVE` (Default and recommended value): entities are not cached unless explicitly marked as cacheable.

- `DISABLE_SELECTIVE`: entities are cached unless explicitly marked as not cacheable.

- `ALL`: all entities are always cached even if marked as non cacheable.

- `NONE`: no entity are cached even if marked as cacheable. This option can make sense to disable second-level cache altogether.

The cache concurrency strategy used by default can be set globaly via the `hibernate.cache.default_cache_concurrency_strategy` configuration property. The values for this property are:

- `read-only`

- `read-write`

- `nonstrict-read-write`

- `transactional`

## 注意

It is recommended to define the cache concurrency strategy per entity rather than using a global one. Use the `@org.hibernate.annotations.Cache` annotation for that.

例21.5 Definition of cache concurrency strategy via `@Cache`

    @Entity

    @Cacheable

    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)

    public class Forest { ... }

Hibernate also let's you cache the content of a collection or the identifiers if the collection contains other entities. Use the `@Cache` annotation on the collection property.

例21.6 Caching collections using annotations

    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)

    @JoinColumn(name="CUST_ID")

    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)

    public SortedSet<Ticket> getTickets() {

        return tickets;

    }

例21.7「@Cache annotation with attributes」shows the`@org.hibernate.annotations.Cache` annotations with its attributes. It allows you to define the caching strategy and region of a given second level cache.

例21.7 `@Cache` annotation with attributes

    @Cache(
        CacheConcurrencyStrategy usage();
        String region() default "";
        String include() default "all";
    )

| usage: the given cache concurrency strategy (NONE, READ_ONLY, NONSTRICT_READ_WRITE, READ_WRITE, TRANSACTIONAL)
| region (optional): the cache region (default to the fqcn of the class or the fq role name of the collection)
| `include` (optional): all to include all properties, non-lazy to only include non lazy properties (default all).

Let's now take a look at Hibernate mapping files. There the `<cache>` element of a class or collection mapping is used to configure the second level cache. Looking at 例21.8「The Hibernate <cache> mapping element」 the parallels to anotations is obvious.

例21.8 The Hibernate `<cache>` mapping element

    <cache
        usage="transactional|read-write|nonstrict-read-write|read-only"
        region="RegionName"
        include="all|non-lazy"
    />

| `usage` (必須) キャッシング戦略を指定します： `transactional`、 `read-write`、 `nonstrict-read-write` または `read-only`
| `region` (オプション、クラスまたはコレクションのロールネームのデフォルト) 2次レベルのキャッシュ領域の名前を指定します
| `include` (オプション、 `all` に対してデフォルト) `non-lazy` は、 属性レベルの lazy フェチが有効になっている場合 `lazy="true"` でマッピングされるエンティティのプロパティはキャッシュされなくてもよいことを指定します。

Alternatively to `<cache>`, you can use `<class-cache>` and `<collection-cache>` elements in `hibernate.cfg.xml`.

Let's now have a closer look at the different usage strategies

### 21.2.2. read only 戦略

もしアプリケーションが読み込みのみ必要で、永続クラスのインスタンスを変更しないなら、 `read-only` キャッシュを使うことが出来ます。これはもっとも単純でもっともパフォーマンスの良い戦略です。クラスタでの使用も完全に安全です。

### 21.2.3. read/write 戦略

アプリケーションがデータを更新する必要があるなら、 `read-write` キャッシュが適当かもしれません。このキャッシュ戦略は、シリアライザブルなトランザクション分離レベルが要求されるなら、決して使うべきではありません。もしキャッシュが JTA 環境で使われるなら、 JTA `TransactionManager` を取得するための方法を示す `hibernate.transaction.manager_lookup_class` プロパティを指定しなければなりません。他の環境では、 `Session.close()` や `Session.disconnect()` が呼ばれたときに、確実にトランザクションが完了していなければなりません。もしクラスタでこの戦略を使いたいなら、基となるキャッシュの実装がロックをサポートしていることを保証しなければなりません。組み込みのキャッシュプロバイダは サポートしていません 。

### 21.2.4. 厳密ではない read/write 戦略

アプリケーションがたまにしかデータを更新する必要はなく（すなわち二つのトランザクションが同時に同じアイテムを更新しようとすることはほとんど起こらない）、厳密なトランザクション分離が要求されないなら、 `nonstrict-read-write` キャッシュが適当かもしれません。もしキャッシュが JTA 環境で使われるなら、 `hibernate.transaction.manager_lookup_class` を指定しなければなりません。他の環境では、 `Session.close()` や `Session.disconnect()` が呼ばれたときに、確実にトランザクションが完了していなければなりません。

### 21.2.5. transactional 戦略

`transactional` キャッシュ戦略は JBoss TreeCache のような完全なトランザクショナルキャッシュプロバイダのサポートを提供します。このようなキャッシュは JTA 環境でのみ使用可能で、 `hibernate.transaction.manager_lookup_class` を指定しなければなりません。

### 21.2.6. Cache-provider/concurrency-strategy compatibility

## 重要項目

すべての同時並行性キャッシュ戦略をサポートしているキャッシュプロバイダはありません。

以下の表はどのプロバイダがどの同時並列性戦略に対応するかを表しています。

表21.2 同時並行性キャッシュ戦略のサポート

キャッシュ | read-only | nonstrict-read-write | read-write | transactional
--- | --- | --- | --- | ---
Hashtable（製品用として意図していません） | yes | yes | yes |
EHCache | yes | yes | yes | yes
OSCache | yes | yes | yes |
SwarmCache | yes | yes |  |
JBoss Cache 1.x | yes |  |  | yes
JBoss Cache 2 | yes |  |  | yes

## 21.3. キャッシュの管理

オブジェクトを `save()` 、 `update()` 、 `saveOrUpdate()` に渡すとき、そして `load()` 、 `get()` 、 `list()` 、 `iterate()` 、 `scroll()` を使ってオブジェクトを復元するときには常に、そのオブジェクトは `Session` の内部キャッシュに追加されます。

次に `flush()` が呼ばれると、オブジェクトの状態はデータベースと同期化されます。もしこの同期が起こることを望まないときや、膨大な数のオブジェクトを処理していてメモリを効率的に扱う必要があるときは、 `evict()` メソッドを使って一次キャッシュからオブジェクトやコレクションを削除することが出来ます。

例21.9 Explcitly evicting a cached instance from the first level cache using `Session.evict()`

    ScrollableResult cats = sess.createQuery("from Cat as cat").scroll(); //a huge result set

    while ( cats.next() ) {

        Cat cat = (Cat) cats.get(0);

        doSomethingWithACat(cat);

        sess.evict(cat);

    }

`Session` はインスタンスがセッションキャッシュに含まれるかどうかを判断するための `contains()` メソッドも提供します。

すべてのオブジェクトをセッションキャッシュから完全に取り除くには、 `Session.clear()` を呼び出してください。

二次キャッシュのために、 `SessionFactory` にはインスタンス、クラス全体、コレクションのインスタンス、コレクション全体をキャッシュから削除するためのメソッドがそれぞれ定義されています。

例21.10 Second-level cache eviction via `SessionFactoty.evict()` and `SessionFacyory.evictCollection()`

    sessionFactory.evict(Cat.class, catId); //evict a particular Cat

    sessionFactory.evict(Cat.class);  //evict all Cats

    sessionFactory.evictCollection("Cat.kittens", catId); //evict a particular collection of kittens

    sessionFactory.evictCollection("Cat.kittens"); //evict all kitten collections

`CacheMode` は特定のセッションが二次キャッシュとどのように相互作用するかを指定します。

- `CacheMode.NORMAL` - アイテムの読み込みと書き込みで二次キャッシュを使います

- `CacheMode.GET` - 読み込みは二次キャッシュから行いますが、データを更新した場合を除いて二次キャッシュに書き込みをしません。

- `CacheMode.PUT` - 二次キャッシュにアイテムを書き込みますが、読み込みには二次キャッシュを使いません。

- `CacheMode.REFRESH` - 二次キャッシュにアイテムを書き込みますが、読み込みには二次キャッシュを使わず、 `hibernate.cache.use_minimal_puts` の影響を受けずに、データベースから読み込むすべてのアイテムの二次キャッシュを強制的にリフレッシュします。

二次キャッシュの内容やクエリキャッシュ領域を見るために、 `Statistics` API を使ってください:

例21.11 Browsing the second-level cache entries via the `Statistics` API

    Map cacheEntries = sessionFactory.getStatistics()

            .getSecondLevelCacheStatistics(regionName)

            .getEntries();

統計情報を有効にして、さらにオプションとして、キャッシュエントリを人がより理解可能な形式で保持することを Hibernate に強制します:

例21.12 Enabling Hibernate statistics

    hibernate.generate_statistics true
    hibernate.cache.use_structured_entries true

## 21.4. クエリキャッシュ

Query result sets can also be cached. This is only useful for queries that are run frequently with the same parameters.

### 21.4.1. Enabling query caching

Caching of query results introduces some overhead in terms of your applications normal transactional processing. For example, if you cache results of a query against Person Hibernate will need to keep track of when those results should be invalidated because changes have been committed against Person. That, coupled with the fact that most applications simply gain no benefit from caching query results, leads Hibernate to disable caching of query results by default. To use query caching, you will first need to enable the query cache:

    hibernate.cache.use_query_cache true

This setting creates two new cache regions:

- `org.hibernate.cache.StandardQueryCache`, holding the cached query results

- `org.hibernate.cache.UpdateTimestampsCache`, holding timestamps of the most recent updates to queryable tables. These are used to validate the results as they are served from the query cache.

## 重要項目

If you configure your underlying cache implementation to use expiry or timeouts is very important that the cache timeout of the underlying cache region for the UpdateTimestampsCache be set to a higher value than the timeouts of any of the query caches. In fact, we recommend that the the UpdateTimestampsCache region not be configured for expiry at all. Note, in particular, that an LRU cache expiry policy is never appropriate.

As mentioned above, most queries do not benefit from caching or their results. So by default, individual queries are not cached even after enabling query caching. To enable results caching for a particular query, call `org.hibernate.Query.setCacheable(true)`. This call allows the query to look for existing cache results or add its results to the cache when it is executed.

## 注意

The query cache does not cache the state of the actual entities in the cache; it caches only identifier values and results of value type. For this reaso, the query cache should always be used in conjunction with the second-level cache for those entities expected to be cached as part of a query result cache (just as with collection caching).

### 21.4.2. Query cache regions

クエリキャッシュの破棄ポリシーを細かく制御したいときは、 `Query.setCacheRegion()` を呼び出して特定のクエリに対するキャッシュ領域を指定することが出来ます。

    List blogs = sess.createQuery("from Blog blog where blog.blogger = :blogger")

            .setEntity("blogger", blogger)

            .setMaxResults(15)

            .setCacheable(true)

            .setCacheRegion("frontpages")

            .list();

If you want to force the query cache to refresh one of its regions (disregard any cached results it finds there) you can use `org.hibernate.Query.setCacheMode(CacheMode.REFRESH)`. In conjunction with the region you have defined for the given query, Hibernate will selectively force the results cached in that particular region to be refreshed. This is particularly useful in cases where underlying data may have been updated via a separate process and is a far more efficient alternative to bulk eviction of the region via `org.hibernate.SessionFactory.evictQueries()`.

## 21.5. コレクションのパフォーマンスの理解

In the previous sections we have covered collections and their applications. In this section we explore some more issues in relation to collections at runtime.

### 21.5.1. 分類

Hibernate は3つの基本的なコレクションの種類を定義しています:

- 値のコレクション

- 一対多関連

- 多対多関連

この分類はさまざまなテーブルや外部キー関連を区別しますが、私たちが知る必要のある関連モデルについてほとんどなにも教えてくれません。関連構造やパフォーマンスの特徴を完全に理解するには、 Hibernate がコレクションの行を更新、削除するために使う主キーの構造もまた考えなければなりません。これは以下の分類を提示します。

- インデックス付きコレクション

- set

- bag

すべてのインデックス付きコレクション （マップ、リスト、配列） は `<key>` と `<index>` カラムからなる主キーを持っています。この場合はコレクションの更新は非常に効率的です。主キーは有用なインデックスになり、 Hibernate が特定の行を更新または削除するときに、その行を効率的に見つけることができます。

set は `<key>` からなる主キーと要素のカラムを持っています。これはコレクション要素のいくつかの型については効率的ではないかもしれません。特に複合要素、大きなテキスト、バイナリフィールドでは非効率です。データベースは複合主キーに効率的にインデックスを付けることができないからです。一方、一対多や多対多関連において、特に人工識別子の場合は同じぐらい効率的です。（余談： `SchemaExport` で実際に `<set>` の主キーを作りたいなら、すべてのカラムで `not-null="true"` を宣言しなければなりません。）

`<idbag>` マッピングは代理キーを定義します。そのため更新は常に非常に効率的です。事実上、これは最善のケースです。

bag は最悪のケースです。 bag は要素の値の重複が可能で、インデックスカラムを持たないため、主キーは定義されないかもしれません。 Hibernate には重複した行を区別する方法がありません。 Hibernate はこの問題の解決のために、変更があったときには常に完全な削除（一つの `DELETE` による）を行い、コレクションの再作成を行います。これは非常に非効率的かもしれません。

一対多関連では、「主キー」はデータベースのテーブルの物理的な主キーではないかもしれないことに注意してください。しかしこの場合でさえ、上記の分類はまだ有用です。（Hibernateがコレクションの個々の行をどうやって「見つけるか」を表しています。）

### 21.5.2. 更新にもっとも効率的なコレクション list、map、idbag、set

上での議論から、インデックス付きコレクションと（普通の） set は要素の追加、削除、更新でもっとも効率的な操作が出来ることは明らかです。

ほぼ間違いなく、多対多関連や値のコレクションにおいて、インデックス付きコレクションが set よりも優れている点が一つ以上あります。 `Set` はその構造のために、 Hibernate は要素が「変更」されたときに行を決して `UPDATE` しません。 `Set` への変更は常に（個々の行の） `INSERT` と `DELETE` によって行います。繰り返しますが、これは一対多関連には当てはまりません。

配列は遅延処理ができないという決まりなので、結論として、list、map、idbag がもっともパフォーマンスの良い（inverse ではない）コレクションタイプとなります。 set もそれほど違いはありません。 Hibernate のアプリケーションでは、 set はコレクションのもっとも共通の種類として期待されます。 "set" の表現は関連モデルではもっとも自然だからです。

しかし、よくデザインされた Hibernate のドメインモデルでは、通常もっとも多いコレクションは事実上 `inverse="true"` を指定した一対多関連です。これらの関連では、更新は多対一の関連端で扱われ、コレクションの更新パフォーマンスの問題は当てはまりません。

### 21.5.3. inverse コレクションにもっとも最適な bag と list

bag を見放してしまう前に、 bag （そして list も）が set よりもずっとパフォーマンスが良い特別なケースを紹介します。 `inverse="true"` のコレクション（一般的な一対多関連の使い方など）で、 bag の要素を初期化（フェッチ）する必要なく bag や list に要素を追加できます。これは `Collection.add()` や `Collection.addAll()` は bag や `List` では常に true を返さなければならないからです （ `Set` とは異なります）。これは以下の共通処理をより速くすることができます。

    Parent p = (Parent) sess.load(Parent.class, id);

    Child c = new Child();

    c.setParent(p);

    p.getChildren().add(c);  //no need to fetch the collection!

    sess.flush();

### 21.5.4. 一括削除

時々、コレクションの要素を一つ一つ削除することは極めて非効率的になることがあります。 Hibernate は愚かではないので、新しい空のコレクションの場合（ `list.clear()` を呼び出した場合など）ではこれをすべきでないことを知っています。この場合は、 Hibernate は `DELETE` を一回発行して、それですべて終わります。

サイズ20のコレクションに一つの要素を追加し、それから二つの要素を削除するとします。 Hibernate は一つの `INSERT` 文と二つの `DELETE` 文を発行します （コレクションが bag でなければ）。これは確かに望ましい動作です。

しかし、18個の要素を削除して2つを残し、それから3つ新しい要素を追加するとします。このとき二つの方法があります。

- 18行を一つ一つ削除して、3行を追加する

- コレクション全体を削除（ `DELETE` の SQL を一回）し、そして5つの要素すべてを（一つずつ）追加する

Hibernate はこの場合に2番目の方法がより速いだろうとわかるほど賢くはありません。（そして Hibernate がこのように賢いことも望ましくないでしょう。このような振る舞いはデータベースのトリガなどを混乱させるかもしれません。）

幸いにも、元のコレクションを捨て（つまり参照をやめて）、現在の要素をすべて持つ新しいコレクションのインスタンスを返すことで、いつでもこの振る舞い（2番目の戦略）を強制することが出来ます。時にこれはとても便利で強力です。

もちろん、一括削除は `inverse="true"` を指定したコレクションには行いません。

## 21.6. パフォーマンスのモニタリング

最適化はモニタリングやパフォーマンスを示す数値がなければ十分に行えません。 Hibernate は内部処理のすべての範囲の数値を提供します。 Hibernate の統計情報は `SessionFactory` 単位で取得可能です。

### 21.6.1. SessionFactory のモニタリング

`SessionFactory` のメトリクスにアクセスするには2つの方法があります。最初の方法は、 `sessionFactory.getStatistics()` を呼び出し、自分で `Statistics` の読み込みや表示を行います。

`StatisticsService` MBean を有効にしていれば、 Hibernate は JMX を使ってメトリクスを発行することもできます。1つの MBean をすべての `SessionFactory` に対して有効にするか、 SessionFactory ごとに一つの MBean を有効にすることが出来ます。最小限の設定例である以下のコードを見てください:

    // MBean service registration for a specific SessionFactory

    Hashtable tb = new Hashtable();

    tb.put("type", "statistics");

    tb.put("sessionFactory", "myFinancialApp");

    ObjectName on = new ObjectName("hibernate", tb); // MBean object name

    StatisticsService stats = new StatisticsService(); // MBean implementation

    stats.setSessionFactory(sessionFactory); // Bind the stats to a SessionFactory

    server.registerMBean(stats, on); // Register the Mbean on the server

    // MBean service registration for all SessionFactory's

    Hashtable tb = new Hashtable();

    tb.put("type", "statistics");

    tb.put("sessionFactory", "all");

    ObjectName on = new ObjectName("hibernate", tb); // MBean object name

    StatisticsService stats = new StatisticsService(); // MBean implementation

    server.registerMBean(stats, on); // Register the MBean on the server

`SessionFactory` に対してモニタリングの開始（終了）を行うことが出来ます。

- 設定時には、 `hibernate.generate_statistics` を `false` にします

- 実行時に、 `sf.getStatistics().setStatisticsEnabled(true)` または `hibernateStatsBean.setStatisticsEnabled(true)` を呼び出します

統計は `clear()` メソッドを使って手動でリセットすることが出来ます。サマリは `logSummary()` メソッドを使って logger に送ることが出来ます（info レベルです）。

### 21.6.2. メトリクス

多くのものがあります。すべての使用可能なカウンタは `Statistics` インターフェースの API に書かれており、3つの分類があります:

- メトリクスは一般的な `Session` の使い方と関係しています。オープンしたセッションの数が JDBC コネクションと関連しているのと同じです。

- メトリクスは要素、コレクション、クエリやキャッシュなど全体に関係しています（別名はグローバルメトリクスです）。

- メトリクスの詳細は特定のエンティティ、コレクション、クエリ、キャッシュ領域に関係しています。

例として、キャッシュのヒット、ヒットミスや、要素、コレクション、クエリの割合、クエリの実行に必要な平均時間を確認できます。ミリ秒の数値は Java の近似を受けることに注意してください。 Hibernate は JVM の精度に制限され、プラットフォームによっては10秒単位でしか正確でないかもしれません。

単純な getter はグローバルメトリクス（すなわち特定のエンティティ、コレクション、キャッシュ領域などに縛られない）にアクセスするために使います。特定のエンティティ、コレクション、キャッシュ領域のメトリクスは、それらの名前や、クエリの HQL 、 SQL 表現によってアクセスすることが出来ます。さらに詳しい情報は、 `Statistics` 、 `EntityStatistics` 、 `CollectionStatistics` 、 `SecondLevelCacheStatistics` 、 `QueryStatistics` API の javadoc を参照してください。以下のコードは簡単な例です:

    Statistics stats = HibernateUtil.sessionFactory.getStatistics();

    double queryCacheHitCount  = stats.getQueryCacheHitCount();

    double queryCacheMissCount = stats.getQueryCacheMissCount();

    double queryCacheHitRatio =

      queryCacheHitCount / (queryCacheHitCount + queryCacheMissCount);

    log.info("Query Hit ratio:" + queryCacheHitRatio);

    EntityStatistics entityStats =

      stats.getEntityStatistics( Cat.class.getName() );

    long changes =

            entityStats.getInsertCount()

            + entityStats.getUpdateCount()

            + entityStats.getDeleteCount();

    log.info(Cat.class.getName() + " changed " + changes + "times"  );

すべてのエンティティ、コレクション、クエリ、キャッシュ領域に対して行う場合は、 `getQueries()` 、 `getEntityNames()`、 `getCollectionRoleNames()` 、 `getSecondLevelCacheRegionNames()` メソッドでそれぞれの名前のリストを取得することが出来ます。

## 第22章 ツールセットガイド

Hibernate を使ったラウンドトリップエンジニアリングは、 Eclipse プラグインやコマンドラインツール、もちろん Ant タスクを使うことで可能です。

Hibernate Tools は現在、既存データベースのリバースエンジニアリングの Ant タスクに加えて、 Eclipse IDE のプラグインを含みます:

- マッピングエディタ: Hibernate の XML マッピングファイル用のエディタで、自動補完と構文強調表示をサポートしています。クラス名やプロパティ/フィールド名に対する自動補完もサポートし、通常の XML エディタよりも強力です。

- Console: コンソールはエクリプスの新しいビューです。コンソールコンフィギュレーションのツリーオーバービューに加えて、永続クラスとその関連の相互作用ビューも得られます。データベースに HQL を実行し、結果を直接エクリプス上で見ることができます。

- 開発ウィザード Hibernate の Eclipse ツールはいくつかのウィザードを提供します。ウィザードを使って Hibernate の設定ファイル (cfg.xml) をすばやく生成したり、既存のデータベーススキーマを POJO のソースファイルと Hibernate のマッピングファイルへと、完全にリバースエンジニアリングすることができます。リバースエンジニアリングウィザードはカスタマイズ可能なテンプレートをサポートします。

より詳しい情報は Hibernate Tools パッケージとそのドキュメントを参照してください。

しかし、 Hibernate のメインパッケージは SchemaExport 、別名 `hbm2ddl` も含みます(Hibernate 「内」でオンザフライで使用できます)。

## 22.1. スキーマの自動生成

DDL は Hibernate ユーティリティによりマッピングファイルから生成することができます。生成されたスキーマはエンティティやコレクションのテーブルに対する参照整合性制約 (主キーと外部キー) を含みます。テーブルとシーケンスはマッピングする識別子ジェネレータに対して生成されます。

DDL はベンダー依存なので、このツールを使うときは、 `hibernate.dialect` プロパティで SQL の `方言` を指定 しなければなりません 。

まず、生成されるスキーマを改善するように、マッピングファイルをカスタマイズしてください。

### 22.1.1. スキーマのカスタマイズ

多くの Hibernate のマッピング要素では、オプションの `length`、 `precision`、 `scale` という名の属性を定義しています。この属性でカラムの長さ、精度、スケールを設定することができます。

    <property name="zip" length="5"/>

    <property name="balance" precision="12" scale="2"/>

`not-null` 属性（テーブルのカラムへ `NOT NULL` 制約を生成する）と `unique` 属性（テーブルのカラムへ `UNIQUE` 制約を生成する）が設定できるタグもあります。

    <many-to-one name="bar" column="barId" not-null="true"/>

    <element column="serialNumber" type="long" not-null="true" unique="true"/>

`unique-key` 属性はカラムをグループ化して一つのキー制約にするために使われます。現在、 `unique-key` 属性で指定された値は制約の指定には 使われず 、マッピングファイルでカラムをグループ化することにのみ使われます。

    <many-to-one name="org" column="orgId" unique-key="OrgEmployeeId"/>

    <property name="employeeId" unique-key="OrgEmployee"/>

`index` 属性はマッピングするカラムを使って生成したインデックスの名前を指定します。複数カラムを１つのインデックスにグループ化できます。単に、同じインデックス名を指定するだけです。

    <property name="lastName" index="CustName"/>

    <property name="firstName" index="CustName"/>

`foreign-key` 属性は、生成された外部キー制約の名前をオーバーライドするために使用できます。

    <many-to-one name="bar" column="barId" foreign-key="FKFooBar"/>

多くのマッピング要素は、子 `<column>` 要素を記述できます。これは複数カラム型のマッピングには特に有用です:

    <property name="name" type="my.customtypes.Name"/>

        <column name="last" not-null="true" index="bar_idx" length="30"/>

        <column name="first" not-null="true" index="bar_idx" length="20"/>

        <column name="initial"/>

    </property

    >

`default` 属性はカラムのデフォルト値を指定します (マッピングしたクラスの新しいインスタンスを保存する前に、マッピングしたプロパティへ同じ値を代入すべきです)。

    <property name="credits" type="integer" insert="false">

        <column name="credits" default="10"/>

    </property

    >

    <version name="version" type="integer" insert="false">

        <column name="version" default="0"/>

    </property

    >

`sql-type` 属性で、デフォルトの Hibernate 型から SQL のデータ型へのマッピングをオーバーライドできます。

    <property name="balance" type="float">

        <column name="balance" sql-type="decimal(13,3)"/>

    </property

    >

`check` 属性でチェック制約を指定することができます。

    <property name="foo" type="integer">

        <column name="foo" check="foo

    > 10"/>

    </property

    >

    <class name="Foo" table="foos" check="bar < 100.0">

        ...

        <property name="bar" type="float"/>

    </class

    >

The following table summarizes these optional attributes.

表22.1 要約

属性 | 値 | 説明
--- | --- | ---
`length` | 数値 | カラムの長さ
`precision` | 数値 | カラムの DECIMAL 型の精度（precision）
`scale` | 数値 | カラムの DECIMAL 型のスケール（scale）
`not-null` | `true|false` | カラムが null 値を取らないことを指定します
`unique` | `true|false` | カラムがユニーク制約を持つことを指定します
`index` | `index_name` | (複数カラムの)インデックスの名前を指定します
`unique-key` | `unique_key_name` | 複数カラムのユニーク制約の名前を指定します
`foreign-key` | `foreign_key_name` | `<one-to-one>`、 `<many-to-one>`、 `<key>`、 または `<many-to-many>` マッピングエレメントのために、関連に対して生成された外部キー制約の名前を指定します。 `inverse="true"` 側は `SchemaExport` によって考慮されないことに注意してください。
`sql-type` | `SQL column type` | デフォルトのカラム型をオーバーライドします ( `<column>` 要素の属性に限る)
`default` | SQL 式 | カラムのデフォルト値を指定します
`check` | SQL 式 | カラムかテーブルに SQL のチェック制約を作成します

`<comment>` 要素で生成するスキーマにコメントを指定することができます。

    <class name="Customer" table="CurCust">

        <comment

    >Current customers only</comment>

        ...

    </class

    >

    <property name="balance">

        <column name="bal">

            <comment

    >Balance in USD</comment>

        </column>

    </property

    >

これにより、生成した DDL に `comment on table` や `comment on column` 文が書かれます。

### 22.1.2. ツールの実行

`SchemaExport` は標準出力に対して DDL スクリプトを書き出し、 DDL 文を実行したりもします。

The following table displays the `SchemaExport` command line options

`java -cp` hibernate_classpaths `org.hibernate.tool.hbm2ddl.SchemaExport` options mapping_files

表22.2 `SchemaExport` のコマンドラインオプション

オプション | 説明
--- | ---
`--quiet` | 標準出力にスクリプトを出力しません
`--drop` | テーブルの削除だけを行います
`--create` | テーブルの生成のみを行います
`--text` | データベースにエクスポートしません
`--output=my_schema.ddl` | DDL スクリプトをファイルに出力します
`--naming=eg.MyNamingStrategy` | `NamingStrategy` を選択
`--config=hibernate.cfg.xml` | XML ファイルから Hibernate の定義情報を読み込みます
`--properties=hibernate.properties` | ファイルからデータベースのプロパティを読み込みます
`--format` | スクリプト内に生成する SQL を読みやすいようにフォーマットします
`--delimiter=;` | スクリプトの行区切り文字を設定します

アプリケーションに `SchemaExport` を組み込むこともできます：

    Configuration cfg = ....;

    new SchemaExport(cfg).create(false, true);

### 22.1.3. プロパティ

次のように、データベースのプロパティを指定することができます。

- `-D`<property> を使って、システムプロパティとして

- `hibernate.properties` ファイル内で

- `--properties` を使って指定したプロパティファイル内で

必要なプロパティは以下のものです：

表22.3 SchemaExport コネクションプロパティ

プロパティ名 | 説明
--- | ---
`hibernate.connection.driver_class` | jdbc のドライバークラス
`hibernate.connection.url` | jdbc の url
`hibernate.connection.username` | データベースのユーザー
`hibernate.connection.password` | ユーザーパスワード
`hibernate.dialect` | データベース方言

### 22.1.4. Ant を使用する

Ant のビルドスクリプトから `SchemaExport` を呼び出すことができます:

    <target name="schemaexport">

        <taskdef name="schemaexport"

            classname="org.hibernate.tool.hbm2ddl.SchemaExportTask"

            classpathref="class.path"/>

        <schemaexport

            properties="hibernate.properties"

            quiet="no"

            text="no"

            drop="no"

            delimiter=";"

            output="schema-export.sql">

            <fileset dir="src">

                <include name="**/*.hbm.xml"/>

            </fileset>

        </schemaexport>

    </target

    >

### 22.1.5. インクリメンタルなスキーマ更新

`SchemaUpdate` ツールは既存のスキーマをインクリメンタルに更新します。 `SchemaUpdate` は JDBC のメタデータ API に強く依存します。そのため、すべての JDBC ドライバでうまくいくとは限らないことに注意してください。

`java -cp` hibernate_classpaths `org.hibernate.tool.hbm2ddl.SchemaUpdate` options mapping_files

表22.4 `SchemaUpdate` のコマンドラインオプション

オプション | 説明
--- | ---
`--quiet` | 標準出力にスクリプトを出力しません
`--text` | データベースにスクリプトをエクスポートしません
`--naming=eg.MyNamingStrategy` | `NamingStrategy` を選択
`--properties=hibernate.properties` | ファイルからデータベースのプロパティを読み込みます
`--config=hibernate.cfg.xml` | `.cfg.xml` ファイルを指定

アプリケーションに `SchemaUpdate` を組み込むことができます：

    Configuration cfg = ....;

    new SchemaUpdate(cfg).execute(false);

### 22.1.6. インクリメンタルなスキーマ更新に対する Ant の使用

Ant スクリプトから `SchemaUpdate` を呼び出すことができます：

    <target name="schemaupdate">

        <taskdef name="schemaupdate"

            classname="org.hibernate.tool.hbm2ddl.SchemaUpdateTask"

            classpathref="class.path"/>

        <schemaupdate

            properties="hibernate.properties"

            quiet="no">

            <fileset dir="src">

                <include name="**/*.hbm.xml"/>

            </fileset>

        </schemaupdate>

    </target

    >

### 22.1.7. Schema validation

`SchemaValidator` ツールは、既存のデータベーススキーマと作成したマッピングドキュメントが「一致する」ことを検証します。 `SchemaValidator` は JDBC のメタデータ API に強く依存することに注意してください。そのため、すべての JDBC ドライバーで作動するものではありません。このツールはテスト時に非常に有用です。

`java -cp` hibernate_classpaths `org.hibernate.tool.hbm2ddl.SchemaValidator` options mapping_files

The following table displays the `SchemaValidator` command line options:

表22.5 `SchemaValidator` のコマンドラインオプション

オプション | 説明
--- | ---
`--naming=eg.MyNamingStrategy` | `NamingStrategy` を選択
`--properties=hibernate.properties` | ファイルからデータベースのプロパティを読み込みます
`--config=hibernate.cfg.xml` | `.cfg.xml` ファイルを指定

`SchemaValidator` をアプリケーションに組み込むことが出来ます:

    Configuration cfg = ....;

    new SchemaValidator(cfg).validate();

### 22.1.8. スキーマのバリデーションに Ant を使用します

Ant スクリプトから `SchemaValidator` を呼び出せます:

    <target name="schemavalidate">

        <taskdef name="schemavalidator"

            classname="org.hibernate.tool.hbm2ddl.SchemaValidatorTask"

            classpathref="class.path"/>

        <schemavalidator

            properties="hibernate.properties">

            <fileset dir="src">

                <include name="**/*.hbm.xml"/>

            </fileset>

        </schemavalidator>

    </target

    >

## 第23章 Additional modules

Hibernate Core also offers integration with some external modules/projects. This includes Hibernate Validator the reference implementation of Bean Validation (JSR 303) and Hibernate Search.

## 23.1. Bean Validation

Bean Validation standardizes how to define and declare domain model level constraints. You can, for example, express that a property should never be null, that the account balance should be strictly positive, etc. These domain model constraints are declared in the bean itself by annotating its properties. Bean Validation can then read them and check for constraint violations. The validation mechanism can be executed in different layers in your application without having to duplicate any of these rules (presentation layer, data access layer). Following the DRY principle, Bean Validation and its reference implementation Hibernate Validator has been designed for that purpose.

The integration between Hibernate and Bean Validation works at two levels. First, it is able to check in-memory instances of a class for constraint violations. Second, it can apply the constraints to the Hibernate metamodel and incorporate them into the generated database schema.

Each constraint annotation is associated to a validator implementation responsible for checking the constraint on the entity instance. A validator can also (optionally) apply the constraint to the Hibernate metamodel, allowing Hibernate to generate DDL that expresses the constraint. With the appropriate event listener, you can execute the checking operation on inserts, updates and deletes done by Hibernate.

When checking instances at runtime, Hibernate Validator returns information about constraint violations in a set of `ConstraintViolation`s. Among other information, the `ConstraintViolation` contains an error description message that can embed the parameter values bundle with the annotation (eg. size limit), and message strings that may be externalized to a `ResourceBundle`.

### 23.1.1. Adding Bean Validation

To enable Hibernate's Bean Validation integration, simply add a Bean Validation provider (preferably Hibernate Validation 4) on your classpath.

### 23.1.2. Configuration

By default, no configuration is necessary.

The `Default` group is validated on entity insert and update and the database model is updated accordingly based on the `Default` group as well.

You can customize the Bean Validation integration by setting the validation mode. Use the `javax.persistence.validation.mode` property and set it up for example in your `persistence.xml` file or your `hibernate.cfg.xml` file. Several options are possible:

- `auto` (default): enable integration between Bean Validation and Hibernate (callback and ddl generation) only if Bean Validation is present in the classpath.

- `none`: disable all integration between Bean Validation and Hibernate

- `callback`: only validate entities when they are either inserted, updated or deleted. An exception is raised if no Bean Validation provider is present in the classpath.

- `ddl`: only apply constraints to the database schema when generated by Hibernate. An exception is raised if no Bean Validation provider is present in the classpath. This value is not defined by the Java Persistence spec and is specific to Hibernate.

## 注意

You can use both `callback` and `ddl` together by setting the property to `callback, dll`

    <persistence ...>

      <persistence-unit ...>

        ...

        <properties>

          <property name="javax.persistence.validation.mode"

                    value="callback, ddl"/>

        </properties>

      </persistence-unit>

    </persistence>

This is equivalent to `auto` except that if no Bean Validation provider is present, an exception is raised.

If you want to validate different groups during insertion, update and deletion, use:

- `javax.persistence.validation.group.pre-persist`: groups validated when an entity is about to be persisted (default to `Default`)

- `javax.persistence.validation.group.pre-update`: groups validated when an entity is about to be updated (default to `Default`)

- `javax.persistence.validation.group.pre-remove`: groups validated when an entity is about to be deleted (default to no group)

- `org.hibernate.validator.group.ddl`: groups considered when applying constraints on the database schema (default to `Default`)

Each property accepts the fully qualified class names of the groups validated separated by a comma (,)

例23.1 Using custom groups for validation

    <persistence ...>

      <persistence-unit ...>

        ...

        <properties>

          <property name="javax.persistence.validation.group.pre-update"

                    value="javax.validation.group.Default, com.acme.group.Strict"/>

          <property name="javax.persistence.validation.group.pre-remove"

                    value="com.acme.group.OnDelete"/>

          <property name="org.hibernate.validator.group.ddl"

                    value="com.acme.group.DDL"/>

        </properties>

      </persistence-unit>

    </persistence>

## 注意

You can set these properties in `hibernate.cfg.xml`, `hibernate.properties` or programmatically.

### 23.1.3. Catching violations

If an entity is found to be invalid, the list of constraint violations is propagated by the `ConstraintViolationException` which exposes the set of `ConstraintViolation`s.

This exception is wrapped in a `RollbackException` when the violation happens at commit time. Otherwise the `ConstraintViolationException` is returned (for example when calling `flush()`. Note that generally, catchable violations are validated at a higher level (for example in Seam / JSF 2 via the JSF - Bean Validation integration or in your business layer by explicitly calling Bean Validation).

An application code will rarely be looking for a `ConstraintViolationException` raised by Hibernate. This exception should be treated as fatal and the persistence context should be discarded (`EntityManager` or `Session`).

### 23.1.4. Database schema

Hibernate uses Bean Validation constraints to generate an accurate database schema:

- `@NotNull` leads to a not null column (unless it conflicts with components or table inheritance)

- `@Size.max` leads to a `varchar(max)` definition for Strings

- `@Min`, `@Max` lead to column checks (like `value <= max`)

- `@Digits` leads to the definition of precision and scale (ever wondered which is which? It's easy now with `@Digits` :) )

These constraints can be declared directly on the entity properties or indirectly by using constraint composition.

For more information check the Hibernate Validator reference documentation.

## 23.2. Hibernate Search

### 23.2.1. Description

Full text search engines like Apache Lucene™ are a very powerful technology to bring free text/efficient queries to applications. If suffers several mismatches when dealing with a object domain model (keeping the index up to date, mismatch between the index structure and the domain model, querying mismatch...) Hibernate Search indexes your domain model thanks to a few annotations, takes care of the database / index synchronization and brings you back regular managed objects from free text queries. Hibernate Search is using Apache Lucene under the cover.

### 23.2.2. Integration with Hibernate Annotations

Hibernate Search integrates with Hibernate Core transparently provided that the Hibernate Search jar is present on the classpath. If you do not wish to automatically register Hibernate Search event listeners, you can set `hibernate.search.autoregister_listeners` to false. Such a need is very uncommon and not recommended.

Check the Hibernate Search reference documentation for more information.

## 第24章 例： 親/子供

新規ユーザーが Hibernate を使ってまず最初に扱うモデルの一つに、親子型のモデル化があります。このモデル化には二つのアプローチが存在します。とりわけ新規ユーザーにとって、さまざまな理由から最も便利だと思われるアプローチは、 `親` から `子供` への `<one-to-many>` 関連により `親` と `子供` の両方をエンティティクラスとしてモデリングする方法です（もう一つの方法は、 `子供` を `<composite-element>` として定義するものです）。これで（ Hibernate における）一対多関連のデフォルトのセマンティクスが、通常の複合要素のマッピングよりも、親子関係のセマンティクスから遠いことがわかります。それでは親子関係を効率的かつエレガントにモデリングするために、 カスケード操作を使った双方向一対多関連 の扱い方を説明します。これはまったく難しいものではありません。

## 24.1. コレクションに関する注意

Hibernate のコレクションは自身のエンティティの論理的な部分と考えられ、決して包含するエンティティのものではありません。これは致命的な違いです。これは以下のような結果になります：

- オブジェクトをコレクションから削除、またはコレクションに追加するとき、コレクションのオーナーのバージョン番号はインクリメントされます。

- もしコレクションから削除されたオブジェクトが値型のインスタンス（例えばコンポジットエレメント) だったならば、そのオブジェクトは永続的ではなくなり、その状態はデータベースから完全に削除されます。同じように、値型のインスタンスをコレクションに追加すると、その状態はすぐに永続的になります。

- 一方、もしエンティティがコレクション（一対多または多対多関連) から削除されても、デフォルトではそれは削除されません。この動作は完全に一貫しています。すなわち、他のエンティティの内部状態を変更しても、関連するエンティティが消滅すべきではないということです。同様に、エンティティがコレクションに追加されても、デフォルトではそのエンティティは永続的にはなりません。

その代わりに、デフォルトの動作では、エンティティをコレクションに追加すると単に二つのエンティティ間のリンクを作成し、一方エンティティを削除するとリンクも削除します。これはすべてのケースにおいて非常に適切です。これが適切でないのは親/子関係の場合です。この場合子供の生存は親のライフサイクルに制限されるからです。

## 24.2. 双方向一対多

`Parent` から `Child` への単純な `<one-to-many>` 関連から始めるとします。

    <set name="children">

        <key column="parent_id"/>

        <one-to-many class="Child"/>

    </set

    >

以下のコードを実行すると、

    Parent p = .....;

    Child c = new Child();

    p.getChildren().add(c);

    session.save(c);

    session.flush();

Hibernate は二つの SQL 文を発行します:

- `c` に対するレコードを生成する `INSERT`

- `p` から `c` へのリンクを作成する `UPDATE`

これは非効率的なだけではなく、 `parent_id` カラムにおいて `NOT NULL` 制約に違反します。コレクションのマッピングで `not-null="true"` と指定することで、 null 制約違反を解決することができます:

    <set name="children">

        <key column="parent_id" not-null="true"/>

        <one-to-many class="Child"/>

    </set

    >

しかしこの解決策は推奨できません。

この動作の根本的な原因は、 `p` から `c` へのリンク（外部キー `parent_id`) は `Child` オブジェクトの状態の一部とは考えられず、そのため `INSERT` によってリンクが生成されないことです。ですから、解決策はリンクを Child マッピングの一部にすることです。

    <many-to-one name="parent" column="parent_id" not-null="true"/>

(また `Child` クラスに `parent` プロパティを追加する必要があります。)

それでは `Child` エンティティがリンクの状態を制御するようになったので、コレクションがリンクを更新しないようにしましょう。それには `inverse` 属性を使います。

    <set name="children" inverse="true">

        <key column="parent_id"/>

        <one-to-many class="Child"/>

    </set

    >

以下のコードを使えば、新しい `Child` を追加することができます。

    Parent p = (Parent) session.load(Parent.class, pid);

    Child c = new Child();

    c.setParent(p);

    p.getChildren().add(c);

    session.save(c);

    session.flush();

これにより、 SQL の `INSERT` 文が一つだけが発行されるようになりました。

もう少し強化するには、 `Parent` の `addChild()` メソッドを作成します。

    public void addChild(Child c) {

        c.setParent(this);

        children.add(c);

    }

`Child` を追加するコードはこのようになります。

    Parent p = (Parent) session.load(Parent.class, pid);

    Child c = new Child();

    p.addChild(c);

    session.save(c);

    session.flush();

## 24.3. ライフサイクルのカスケード

明示的に `save()` をコールするのはまだ煩わしいものです。これをカスケードを使って対処します。

    <set name="children" inverse="true" cascade="all">

        <key column="parent_id"/>

        <one-to-many class="Child"/>

    </set

    >

これにより先ほどのコードをこのように単純化します

    Parent p = (Parent) session.load(Parent.class, pid);

    Child c = new Child();

    p.addChild(c);

    session.flush();

同様に `Parent` を保存または削除するときに、子供を一つ一つ取り出して扱う必要はありません。以下のコードは `p` を削除し、そしてデータベースからその子供をすべて削除します。

    Parent p = (Parent) session.load(Parent.class, pid);

    session.delete(p);

    session.flush();

しかしこのコードは

    Parent p = (Parent) session.load(Parent.class, pid);

    Child c = (Child) p.getChildren().iterator().next();

    p.getChildren().remove(c);

    c.setParent(null);

    session.flush();

データベースから `c` を削除しません。 `p` へのリンクを削除する（そしてこのケースでは `NOT NULL` 制約違反を引き起こす）だけです。 `Child` の `delete()` を明示する必要があります。

    Parent p = (Parent) session.load(Parent.class, pid);

    Child c = (Child) p.getChildren().iterator().next();

    p.getChildren().remove(c);

    session.delete(c);

    session.flush();

今このケースでは実際に `Child` が親なしでは存在できないようになりました。そのため、もしコレクションから `Child` を取り除く場合、これも削除します。そのためには `cascade="all-delete-orphan"` を使わなければなりません。

    <set name="children" inverse="true" cascade="all-delete-orphan">

        <key column="parent_id"/>

        <one-to-many class="Child"/>

    </set

    >

注記：コレクションのマッピングで `inverse="true"` と指定しても、コレクションの要素のイテレーションによって、依然カスケードが実行されます。そのため、もしカスケードでオブジェクトをセーブ、削除、更新する必要があるなら、それをコレクションに追加しなければなりません。単に `setParent()` を呼ぶだけでは不十分です。

## 24.4. カスケードと unsaved-value

Suppose we loaded up a `Parent` in one `Session`, made some changes in a UI action and wanted to persist these changes in a new session by calling `update()`. The `Parent` will contain a collection of children and, since the cascading update is enabled, Hibernate needs to know which children are newly instantiated and which represent existing rows in the database. We will also assume that both `Parent` and `Child` have generated identifier properties of type `Long`. Hibernate will use the identifier and version/timestamp property value to determine which of the children are new. (See 「自動的な状態検出」.) In Hibernate3, it is no longer necessary to specify an `unsaved-value` explicitly.

以下のコードは `parent` と `child` を更新し、 `newChild` を挿入します。

    //parent and child were both loaded in a previous session

    parent.addChild(child);

    Child newChild = new Child();

    parent.addChild(newChild);

    session.update(parent);

    session.flush();

これらは生成された識別子の場合には非常に良いのですが、割り当てられた識別子と複合識別子の場合はどうでしょうか？これは Hibernate が、（ユーザーにより割り当てられた識別子を持つ）新しくインスタンス化されたオブジェクトと、以前の Session でロードされたオブジェクトを区別できないため、より難しいです。この場合、 Hibernate はタイムスタンプかバージョンのプロパティのどちらかを使うか、二次キャッシュに問い合わせます。最悪の場合、行が存在するかどうかデータベースを見ます。

## 24.5. 結論

ここではかなりの量を要約したので、最初の頃は混乱しているように思われるかもしれません。しかし実際は、すべて非常に良く動作します。ほとんどの Hibernate アプリケーションでは、多くの場面で親子パターンを使用します。

最初の段落で代替方法について触れました。上記のような問題は `<composite-element>` マッピングの場合は存在せず、にもかかわらずそれは確かに親子関係のセマンティクスを持ちます。しかし残念ながら、複合要素クラスには２つの大きな制限があります： 1つは複合要素はコレクションを持つことができないことです。もうひとつは、ユニークな親ではないエンティティの子供となるべきではないということです

## 第25章 例: Weblog アプリケーション

## 25.1. 永続クラス

永続クラスがウェブログと、ウェブログに掲示された項目を表しています。それらは通常の親子関係としてモデリングされますが、 set ではなく順序を持った bag を使用することにします。

    package eg;

    import java.util.List;

    public class Blog {

        private Long _id;

        private String _name;

        private List _items;

        public Long getId() {

            return _id;

        }

        public List getItems() {

            return _items;

        }

        public String getName() {

            return _name;

        }

        public void setId(Long long1) {

            _id = long1;

        }

        public void setItems(List list) {

            _items = list;

        }

        public void setName(String string) {

            _name = string;

        }

    }

    package eg;

    import java.text.DateFormat;

    import java.util.Calendar;

    public class BlogItem {

        private Long _id;

        private Calendar _datetime;

        private String _text;

        private String _title;

        private Blog _blog;

        public Blog getBlog() {

            return _blog;

        }

        public Calendar getDatetime() {

            return _datetime;

        }

        public Long getId() {

            return _id;

        }

        public String getText() {

            return _text;

        }

        public String getTitle() {

            return _title;

        }

        public void setBlog(Blog blog) {

            _blog = blog;

        }

        public void setDatetime(Calendar calendar) {

            _datetime = calendar;

        }

        public void setId(Long long1) {

            _id = long1;

        }

        public void setText(String string) {

            _text = string;

        }

        public void setTitle(String string) {

            _title = string;

        }

    }

## 25.2. Hibernate のマッピング

XML マッピングは、今ではとても簡単なはずです。

    <?xml version="1.0"?>

    <!DOCTYPE hibernate-mapping PUBLIC

        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

    <hibernate-mapping package="eg">

        <class

            name="Blog"

            table="BLOGS">

            <id

                name="id"

                column="BLOG_ID">

                <generator class="native"/>

            </id>

            <property

                name="name"

                column="NAME"

                not-null="true"

                unique="true"/>

            <bag

                name="items"

                inverse="true"

                order-by="DATE_TIME"

                cascade="all">

                <key column="BLOG_ID"/>

                <one-to-many class="BlogItem"/>

            </bag>

        </class>

    </hibernate-mapping

    >

    <?xml version="1.0"?>

    <!DOCTYPE hibernate-mapping PUBLIC

        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

    <hibernate-mapping package="eg">

        <class

            name="BlogItem"

            table="BLOG_ITEMS"

            dynamic-update="true">

            <id

                name="id"

                column="BLOG_ITEM_ID">

                <generator class="native"/>

            </id>

            <property

                name="title"

                column="TITLE"

                not-null="true"/>

            <property

                name="text"

                column="TEXT"

                not-null="true"/>

            <property

                name="datetime"

                column="DATE_TIME"

                not-null="true"/>

            <many-to-one

                name="blog"

                column="BLOG_ID"

                not-null="true"/>

        </class>

    </hibernate-mapping

    >

## 25.3. Hibernate のコード

以下のクラスは、 Hibernate でこれらのクラスを使ってできるいくつかのことを示しています。

    package eg;

    import java.util.ArrayList;

    import java.util.Calendar;

    import java.util.Iterator;

    import java.util.List;

    import org.hibernate.HibernateException;

    import org.hibernate.Query;

    import org.hibernate.Session;

    import org.hibernate.SessionFactory;

    import org.hibernate.Transaction;

    import org.hibernate.cfg.Configuration;

    import org.hibernate.tool.hbm2ddl.SchemaExport;

    public class BlogMain {

        private SessionFactory _sessions;

        public void configure() throws HibernateException {

            _sessions = new Configuration()

                .addClass(Blog.class)

                .addClass(BlogItem.class)

                .buildSessionFactory();

        }

        public void exportTables() throws HibernateException {

            Configuration cfg = new Configuration()

                .addClass(Blog.class)

                .addClass(BlogItem.class);

            new SchemaExport(cfg).create(true, true);

        }

        public Blog createBlog(String name) throws HibernateException {

            Blog blog = new Blog();

            blog.setName(name);

            blog.setItems( new ArrayList() );

            Session session = _sessions.openSession();

            Transaction tx = null;

            try {

                tx = session.beginTransaction();

                session.persist(blog);

                tx.commit();

            }

            catch (HibernateException he) {

                if (tx!=null) tx.rollback();

                throw he;

            }

            finally {

                session.close();

            }

            return blog;

        }

        public BlogItem createBlogItem(Blog blog, String title, String text)

                            throws HibernateException {

            BlogItem item = new BlogItem();

            item.setTitle(title);

            item.setText(text);

            item.setBlog(blog);

            item.setDatetime( Calendar.getInstance() );

            blog.getItems().add(item);

            Session session = _sessions.openSession();

            Transaction tx = null;

            try {

                tx = session.beginTransaction();

                session.update(blog);

                tx.commit();

            }

            catch (HibernateException he) {

                if (tx!=null) tx.rollback();

                throw he;

            }

            finally {

                session.close();

            }

            return item;

        }

        public BlogItem createBlogItem(Long blogid, String title, String text)

                            throws HibernateException {

            BlogItem item = new BlogItem();

            item.setTitle(title);

            item.setText(text);

            item.setDatetime( Calendar.getInstance() );

            Session session = _sessions.openSession();

            Transaction tx = null;

            try {

                tx = session.beginTransaction();

                Blog blog = (Blog) session.load(Blog.class, blogid);

                item.setBlog(blog);

                blog.getItems().add(item);

                tx.commit();

            }

            catch (HibernateException he) {

                if (tx!=null) tx.rollback();

                throw he;

            }

            finally {

                session.close();

            }

            return item;

        }

        public void updateBlogItem(BlogItem item, String text)

                        throws HibernateException {

            item.setText(text);

            Session session = _sessions.openSession();

            Transaction tx = null;

            try {

                tx = session.beginTransaction();

                session.update(item);

                tx.commit();

            }

            catch (HibernateException he) {

                if (tx!=null) tx.rollback();

                throw he;

            }

            finally {

                session.close();

            }

        }

        public void updateBlogItem(Long itemid, String text)

                        throws HibernateException {

            Session session = _sessions.openSession();

            Transaction tx = null;

            try {

                tx = session.beginTransaction();

                BlogItem item = (BlogItem) session.load(BlogItem.class, itemid);

                item.setText(text);

                tx.commit();

            }

            catch (HibernateException he) {

                if (tx!=null) tx.rollback();

                throw he;

            }

            finally {

                session.close();

            }

        }

        public List listAllBlogNamesAndItemCounts(int max)

                        throws HibernateException {

            Session session = _sessions.openSession();

            Transaction tx = null;

            List result = null;

            try {

                tx = session.beginTransaction();

                Query q = session.createQuery(

                    "select blog.id, blog.name, count(blogItem) " +

                    "from Blog as blog " +

                    "left outer join blog.items as blogItem " +

                    "group by blog.name, blog.id " +

                    "order by max(blogItem.datetime)"

                );

                q.setMaxResults(max);

                result = q.list();

                tx.commit();

            }

            catch (HibernateException he) {

                if (tx!=null) tx.rollback();

                throw he;

            }

            finally {

                session.close();

            }

            return result;

        }

        public Blog getBlogAndAllItems(Long blogid)

                        throws HibernateException {

            Session session = _sessions.openSession();

            Transaction tx = null;

            Blog blog = null;

            try {

                tx = session.beginTransaction();

                Query q = session.createQuery(

                    "from Blog as blog " +

                    "left outer join fetch blog.items " +

                    "where blog.id = :blogid"

                );

                q.setParameter("blogid", blogid);

                blog  = (Blog) q.uniqueResult();

                tx.commit();

            }

            catch (HibernateException he) {

                if (tx!=null) tx.rollback();

                throw he;

            }

            finally {

                session.close();

            }

            return blog;

        }

        public List listBlogsAndRecentItems() throws HibernateException {

            Session session = _sessions.openSession();

            Transaction tx = null;

            List result = null;

            try {

                tx = session.beginTransaction();

                Query q = session.createQuery(

                    "from Blog as blog " +

                    "inner join blog.items as blogItem " +

                    "where blogItem.datetime

    > :minDate"

                );

                Calendar cal = Calendar.getInstance();

                cal.roll(Calendar.MONTH, false);

                q.setCalendar("minDate", cal);

                result = q.list();

                tx.commit();

            }

            catch (HibernateException he) {

                if (tx!=null) tx.rollback();

                throw he;

            }

            finally {

                session.close();

            }

            return result;

        }

    }

## 第26章 例： いろいろなマッピング

この章では、より複雑な関連のマッピングをいくつか紹介します。

## 26.1. 雇用者/従業員

`Employer` と `Employee` の関係を表す以下のモデルは、関連の表現に実際のエンティティクラス （ `Employment` ） を使います。なぜなら、同じ2つのパーティに複数の期間雇用されるということがありえるからです。お金の値と従業員の名前をモデル化するためにコンポーネントを使っています。

マッピングドキュメントの一例です：

    <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

    >

`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

## 26.2. 作者/作品

`Work` 、 `Author` そして `Person` の関係を表す以下のモデルを考えてみてください。 `Work` と `Author` の関係を多対多関連で表しています。 `Author` と `Person` の関係は一対一関連として表しています。他には `Author` が `Person` を拡張するという方法もあります。

以下のマッピングドキュメントはこのような関係を正確に表現しています:

    <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

    >

このマッピングには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

## 26.3. 顧客/注文/製品

さて、 `Customer` 、 `Order` 、 `LineItem` 、 `Product` の関係を表すモデルを考えてみましょう。 `Customer` と `Order` は一対多の関連ですが、 `Order` / `LineItem` / `Product` はどのように表現するべきでしょうか？ `LineItem` を、 `Order` と `Product` の多対多関連を表現する関連クラスとしてマッピングしました。 Hibernate ではこれをコンポジット要素と呼びます。

マッピングドキュメント：

    <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

    >

`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

## 26.4. 種々雑多なマッピング例

ここにある例はすべて Hibernate のテストスイートから取りました。そこには、他にもたくさんのマッピングの例があります。 Hibernate ディストリビューションの `test` フォルダを見てください。

### 26.4.1. 「型付けされた」一対一関連

    <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

    >

### 26.4.2. 複合キーの例

    <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

    >

### 26.4.3. 複合キー属性を共有する多対多

    <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>

### 26.4.4. 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

    >

### 26.4.5. 代替キーの関連

    <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

    >

## 第27章 ベストプラクティス

クラスは細かい粒度で書き `<component>` でマッピングしましょう。

  `street` （通り）、 `suburb` （都市）、 `state` （州）、 `postcode` （郵便番号）をカプセル化する `Address` （住所）クラスを使いましょう。そうすればコードが再利用しやすくなり、リファクタリングも簡単になります。

永続クラスには識別子プロパティを定義しましょう。

  Hibernate では識別子プロパティはオプションですが、使用すべき理由がたくさんあります。識別子は「人工的」（生成された、業務的な意味を持たない）なものにすることをおすすめします。

自然キーを見つけましょう。

  すべてのエンティティに対して自然キーを見つけて、 `<natural-id>` でマッピングしましょう。自然キーを構成するプロパティを比較するために、 `equals()` と `hashCode()` を実装しましょう。

クラスのマッピングはそれぞれのクラス専用のファイルに書きましょう。

  単一の巨大なマッピングドキュメントを使用しないでください。 `com.eg.Foo` クラスなら `com/eg/Foo.hbm.xml` ファイルにマッピングしましょう。このことは、特にチームでの開発に意味があります。

リソースとしてマッピングをロードしましょう。

  マッピングを、それらがマッピングするクラスと一緒に配置しましょう。

クエリ文字列を外部に置くことを考えましょう

  クエリが ANSI 標準でない SQL 関数を呼んでいるなら、これはよいプラクティスです。クエリ文字列をマッピングファイルへ外出しすればアプリケーションがポータブルになります。

バインド変数を使いましょう。

  JDBC の場合と同じように、定数でない値は必ず "?" で置き換えましょう。定数でない値をバインドするために、クエリで文字列操作を使ってはいけません。名前付きのパラメータを使うようにするとさらに良いです。

JDBC コネクションを管理してはいけません。

  Hibernate ではアプリケーションが JDBC コネクションを管理することが許されています。しかしこれは最終手段だと思ってください。組み込みのコネクションプロバイダを使うことができなければ、 `org.hibernate.connection.ConnectionProvider` を実装することを考えてください。

カスタム型の使用を考えましょう。

  あるライブラリから持ってきた Java 型を永続化する必要があるとしましょう。しかしその型には、コンポーネントとしてマッピングするために必要なアクセサがないとします。このような場合は `org.hibernate.UserType` の実装を考えるべきです。そうすれば Hibernate 型との実装変換を心配せずにアプリケーションのコードを扱えます。

ボトルネックを解消するには JDBC をハンドコードしましょう。

  In performance-critical areas of the system, some kinds of operations might benefit from direct JDBC. Do not assume, however, that JDBC is necessarily faster. Please wait until you know something is a bottleneck. If you need to use direct JDBC, you can open a Hibernate `Session`, wrap your JDBC operation as a `org.hibernate.jdbc.Work` object and using that JDBC connection. This way you can still use the same transaction strategy and underlying connection provider.

`Session` のフラッシュを理解しましょう。

  Session が永続状態をデータベースと同期させることがときどきあります。しかしこれがあまりに頻繁に起こるようだと、パフォーマンスに影響が出てきます。自動フラッシュを無効にしたり、特定のトランザクションのクエリや操作の順番を変更することで、不必要なフラッシュを最小限にできます。

3層アーキテクチャでは分離オブジェクトの使用を考えましょう。

  サーブレット / セッション Bean アーキテクチャを使うとき、サーブレット層 / JSP 層間でセッション Bean でロードした永続オブジェクトをやり取りできます。その際リクエストごとに新しい Session を使ってください。また `Session.merge()` や `Session.saveOrUpdate()` を使って、オブジェクトとデータベースを同期させてください。

2層アーキテクチャでは長い永続コンテキストの使用を考えましょう。

  最高のスケーラビリティを得るには、データベーストランザクションをできるだけ短くしなければなりません。しかし長い間実行する アプリケーショントランザクション の実装が必要なことはしばしばです。これはユーザーの視点からは1個の作業単位（unit of work）になります。アプリケーショントランザクションはいくつかのクライアントのリクエスト/レスポンスサイクルにまたがります。アプリケーショントランザクションの実装に分離オブジェクトを使うのは一般的です。そうでなければ、2層アーキテクチャの場合は特に適切なことですが、アプリケーショントランザクションのライフサイクル全体に対して単一のオープンな永続化コンテキスト（セッション）を維持してください。そして単純にリクエストの最後に JDBC コネクションから切断し、次のリクエストの最初に再接続します。決して複数のアプリケーショントランザクションユースケースに渡って1個の Session を使い回さないでください。そうでなければ、古いデータで作業することになります。

例外を復帰可能なものとして扱ってはいけません。

  これは「ベスト」プラクティス以上の、必須のプラクティスです。例外が発生したときは `Transaction` をロールバックして、 `Session` をクローズしてください。そうしないと Hibernate はメモリの状態が永続状態を正確に表現していることを保証できません。この特別な場合として、与えられた識別子を持つインスタンスがデータベースに存在するかどうかを判定するために、 `Session.load()` を使うことはやめてください。その代わりに `Session.get()` かクエリを使ってください。

関連にはなるべく遅延フェッチを使いましょう。

  即時フェッチは控えめにしましょう。二次キャッシュには完全に保持されないようなクラスの関連には、プロキシと遅延コレクションを使ってください。キャッシュされるクラスの関連、つまりキャッシュがヒットする可能性が非常に高い関連は、 `lazy="false"` で積極的なフェッチを明示的に無効にしてください。結合フェッチが適切な特定のユースケースには、クエリで `left join fetch` を使ってください。

フェッチされていないデータに関わる問題を避けるために、 ビューの中でオープンセッションを使う (open session in view) パターンか、統制された 組み立てフェーズ (assembly phase) を使いましょう。

  Hibernate は Data Transfer Objects (DTO) を書く退屈な作業から開発者を解放します。伝統的な EJB アーキテクチャでは DTO は2つ目的があります： 1つ目は、エンティティ Bean がシリアライズされない問題への対策です。2つ目は、プレゼンテーション層に制御が戻る前に、ビューに使われるすべてのデータがフェッチされて、 DTO に復元されるような組み立てフェーズを暗黙的に定義します。 Hibernate では1つ目の目的が不要になります。しかしビューのレンダリング処理の間、永続コンテキスト（セッション）をオープンにしたままにしなければ、組み立てフェーズはまだ必要です（分離オブジェクトの中のどのデータが利用可能かについて、プレゼンテーション層と厳密な取り決めをしているビジネスメソッドを考えてみてください）。これは Hibernate 側の問題ではありません。トランザクション内で安全にデータアクセスするための基本的な要件です。

Hibernate からビジネスロジックを抽象化することを考えましょう。

  インターフェースで（Hibernate の）データアクセスコードを隠蔽しましょう。 DAO と Thread Local Session パターンを組み合わせましょう。 `UserType` で Hibernate に関連付けると、ハンドコードした JDBC で永続化するクラスを持つこともできます。（このアドバイスは「十分大きな」アプリケーションに対してのものです。テーブルが5個しかないようなアプリケーションには当てはまりません。）

珍しい関連マッピングは使わないようにしましょう。

  よいユースケースに本当の多対多関連があることは稀です。ほとんどの場合「リンクテーブル」の付加的な情報が必要になります。この場合、リンククラスに2つの一対多関連を使う方がずっとよいです。実際ほとんどの場合、関連は一対多と多対一なので、他のスタイルの関連を使うときは本当に必要かどうかを考えてみてください。

なるべく双方向関連にしましょう。

  単方向関連は双方向に比べて検索が難しくなります。大きなアプリケーションでは、ほとんどすべての関連が双方向にナビゲーションできなければなりません。

## 第28章 Database Portability Considerations

## 28.1. Portability Basics

One of the selling points of Hibernate (and really Object/Relational Mapping as a whole) is the notion of database portability. This could mean an internal IT user migrating from one database vendor to another, or it could mean a framework or deployable application consuming Hibernate to simultaneously target multiple database products by their users. Regardless of the exact scenario, the basic idea is that you want Hibernate to help you run against any number of databases without changes to your code, and ideally without any changes to the mapping metadata.

## 28.2. Dialect

The first line of portability for Hibernate is the dialect, which is a specialization of the `org.hibernate.dialect.Dialect` contract. A dialect encapsulates all the differences in how Hibernate must communicate with a particular database to accomplish some task like getting a sequence value or structuring a SELECT query. Hibernate bundles a wide range of dialects for many of the most popular databases. If you find that your particular database is not among them, it is not terribly difficult to write your own.

## 28.3. Dialect resolution

Originally, Hibernate would always require that users specify which dialect to use. In the case of users looking to simultaneously target multiple databases with their build that was problematic. Generally this required their users to configure the Hibernate dialect or defining their own method of setting that value.

Starting with version 3.2, Hibernate introduced the notion of automatically detecting the dialect to use based on the `java.sql.DatabaseMetaData` obtained from a `java.sql.Connection` to that database. This was much better, expect that this resolution was limited to databases Hibernate know about ahead of time and was in no way configurable or overrideable.

Starting with version 3.3, Hibernate has a fare more powerful way to automatically determine which dialect to should be used by relying on a series of delegates which implement the `org.hibernate.dialect.resolver.DialectResolver` which defines only a single method:

    public Dialect resolveDialect(DatabaseMetaData metaData) throws JDBCConnectionException

The basic contract here is that if the resolver 'understands' the given database metadata then it returns the corresponding Dialect; if not it returns null and the process continues to the next resolver. The signature also identifies `org.hibernate.exception.JDBCConnectionException` as possibly being thrown. A JDBCConnectionException here is interpreted to imply a "non transient" (aka non-recoverable) connection problem and is used to indicate an immediate stop to resolution attempts. All other exceptions result in a warning and continuing on to the next resolver.

The cool part about these resolvers is that users can also register their own custom resolvers which will be processed ahead of the built-in Hibernate ones. This might be useful in a number of different situations: it allows easy integration for auto-detection of dialects beyond those shipped with HIbernate itself; it allows you to specify to use a custom dialect when a particular database is recognized; etc. To register one or more resolvers, simply specify them (seperated by commas, tabs or spaces) using the 'hibernate.dialect_resolvers' configuration setting (see the `DIALECT_RESOLVERS` constant on `org.hibernate.cfg.Environment`).

## 28.4. Identifier generation

When considering portability between databases, another important decision is selecting the identifier generation stratagy you want to use. Originally Hibernate provided the native generator for this purpose, which was intended to select between a sequence, identity, or table strategy depending on the capability of the underlying database. However, an insidious implication of this approach comes about when targtetting some databases which support identity generation and some which do not. identity generation relies on the SQL definition of an IDENTITY (or auto-increment) column to manage the identifier value; it is what is known as a post-insert generation strategy becauase the insert must actually happen before we can know the identifier value. Because Hibernate relies on this identifier value to uniquely reference entities within a persistence context it must then issue the insert immediately when the users requests the entitiy be associated with the session (like via save() e.g.) regardless of current transactional semantics.

## 注意

Hibernate was changed slightly once the implication of this was better understood so that the insert is delayed in cases where that is feasible.

The underlying issue is that the actual semanctics of the application itself changes in these cases.

Starting with version 3.2.3, Hibernate comes with a set of enhanced identifier generators targetting portability in a much different way.

## 注意

There are specifically 2 bundled enhancedgenerators:

- `org.hibernate.id.enhanced.SequenceStyleGenerator`

- `org.hibernate.id.enhanced.TableGenerator`

The idea behind these generators is to port the actual semantics of the identifer value generation to the different databases. For example, the `org.hibernate.id.enhanced.SequenceStyleGenerator` mimics the behavior of a sequence on databases which do not support sequences by using a table.

## 28.5. Database functions

## 警告

This is an area in Hibernate in need of improvement. In terms of portability concerns, this function handling currently works pretty well from HQL; however, it is quite lacking in all other aspects.

SQL functions can be referenced in many ways by users. However, not all databases support the same set of functions. Hibernate, provides a means of mapping a logical function name to a delegate which knows how to render that particular function, perhaps even using a totally different physical function call.

## 重要項目

Technically this function registration is handled through the `org.hibernate.dialect.function.SQLFunctionRegistry` class which is intended to allow users to provide custom function definitions without having to provide a custom dialect. This specific behavior is not fully completed as of yet.

It is sort of implemented such that users can programatically register functions with the `org.hibernate.cfg.Configuration` and those functions will be recognized for HQL.

## 28.6. Type mappings

This section scheduled for completion at a later date...

## References

[PoEAA] Patterns of Enterprise Application Architecture. 0-321-12742-0. ： Fowler Martin [FAMILY Given]. 製作著作 © 2003 Pearson Education, Inc.. Addison-Wesley Publishing Company.

[JPwH] Java Persistence with Hibernate. Second Edition of Hibernate in Action. 1-932394-88-5. http://www.manning.com/bauer2 . ： Bauer Christian [FAMILY Given] 、 King Gavin [FAMILY Given]. 製作著作 © 2007 Manning Publications Co.. Manning Publications Co..

製作著作 © 2004 Red Hat, Inc.