Thursday, May 8, 2008

HIBERNATE - Relational Persistence for Idiomatic Java - 1

Hibernateレファレンスドキュメンテーション
3.2.2

Table of Contents(コンテンツテーブル)
Preface(序文)
1. Introduction to Hibernate(Hibernateの紹介)
1.1. Preface(序文)
1.2. Part 1 - The first Hibernate Application(パート1 - 最初のHibernateアプリケーション)
1.2.1. The first class(最初のクラス)
1.2.2. The mapping file(マッピングファイル)
1.2.3. Hibernate configuration(Hibernateの設定)
1.2.4. Building with Ant(Antによるビルド)
1.2.5. Startup and helpers(スタートアップとヘルパ)
1.2.6. Loading and storing objects(オブジェクトのロードと格納)
1.3. Part 2 - Mapping associations(パート - 関連のマッピング)
1.3.1. Mapping the Person class(Personクラスのマッピング)
1.3.2. A unidirectional Set-based association(単方向Setベース関連)
1.3.3. Working the association(関連を働かせる)
1.3.4. Collection of values(値のコレクション)
1.3.5. Bi-directional associations(双方向関連)
1.3.6. Working bi-directional links(双方向リンクの動作)
1.4. Part 3 - The EventManager web application(パート - EventManager Webアプリケーション)
1.4.1. Writing the basic servlet(基本的なServletの記述)
1.4.2. Processing and rendering(処理と描画)
1.4.3. Deploying and testing(デプロイとテスト)
1.5. Summary(要約)
HIBERNATE - Relational Persistence for Idiomatic Java
Hibernate Reference Documentation
Hibernateレファレンスドキュメンテーション
3.2.2

Table of Contents(コンテンツテーブル)
Preface(序文)
1. Introduction to Hibernate(Hibernateの紹介)
1.1. Preface(序文)
1.2. Part 1 - The first Hibernate Application(パート1 - 最初のHibernateアプリケーション)
1.2.1. The first class(最初のクラス)
1.2.2. The mapping file(マッピングファイル)
1.2.3. Hibernate configuration(Hibernateの設定)
1.2.4. Building with Ant(Antによるビルド)
1.2.5. Startup and helpers(スタートアップとヘルパ)
1.2.6. Loading and storing objects(オブジェクトのロードと格納)
1.3. Part 2 - Mapping associations(パート - 関連のマッピング)
1.3.1. Mapping the Person class(Personクラスのマッピング)
1.3.2. A unidirectional Set-based association(単方向Setベース関連)
1.3.3. Working the association(関連を働かせる)
1.3.4. Collection of values(値のコレクション)
1.3.5. Bi-directional associations(双方向関連)
1.3.6. Working bi-directional links(双方向リンクの動作)
1.4. Part 3 - The EventManager web application(パート - EventManager Webアプリケーション)
1.4.1. Writing the basic servlet(基本的なServletの記述)
1.4.2. Processing and rendering(処理と描画)
1.4.3. Deploying and testing(デプロイとテスト)
1.5. Summary(要約)
Preface(序文)
Working with object-oriented software and a relational database can be cumbersome and time consuming in today's enterprise environments. Hibernate is an object/relational mapping tool for Java environments. The term object/relational mapping (ORM) refers to the technique of mapping a data representation from an object model to a relational data model with a SQL-based schema.
今日のエンタープライズ環境では、オブジェクト指向/リレーショナルデータベースの仕事は、 厄介で時間のかかるものであることがあります。Hibernateは、 Java環境のオブジェクト/リレーショナル・マッピングツールです。 オブジェクト/リレーショナル・マッピング(ORM)という言葉は、 オブジェクト・モデルで表現されたデータをリレーショナル、 つまりSQLベースの構造のデータに対応付ける技術のことを言います。
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 and can significantly reduce development time otherwise spent with manual data handling in SQL and JDBC.
HibernateJavaクラスからデータベースのテーブルへのマッピングを行うだけではなく、 データのクエリと復元機能を提供します。そのおかげで、 SQLJDBCによる手作業でデータを操作する方法に比べて、開発時間を格段に減らすことができます。
Hibernates goal is to relieve the developer from 95 percent of common data persistence related programming tasks. 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の目標は、プログラミング作業に関わる、共通のデータ永続化作業の95%から、 開発者を解放することです。 Hibernateは、データベース上でビジネス・ロジックを実装するストアド・プロシージャを使うだけの、 データ中心アプリケーションに対するベスト・ソリューションであるだけではありません。 オブジェクト指向ドメインモデルと、Javaベースの中間層におけるビジネス・ロジックに対して最も有用です。 しかし、Hibernateはベンダ固有のSQLコードを取り除いたり、カプセル化できます。 また表形式の表現からオブジェクトのグラフへと、リザルト・セットを翻訳する共通作業の手助けもします。
If you are new to Hibernate and Object/Relational Mapping or even Java, please follow these steps:
もしHibernateとオブジェクト/リレーショナル・マッピング、さらにはJavaが初めてなら、 以下のステップで進んでください:
1.      Read Chapter 1, Introduction to Hibernate for a tutorial with step-by-step instructions. The source code for the tutorial is included in the distribution in thedoc/reference/tutorial/ directory.
段階的な指導のためにチュートリアルChapter 1, Introduction to Hibernate(Hibernateの紹介)を読んで下さい。チュートリアルのためのソースコードは、doc/reference/tutorial/directoryに含まれています。
2.      Read Chapter 2, Architecture to understand the environments where Hibernate can be used.
Hibernateを使える環境を理解するためにChapter 2, Architecture(アーキテクチャ)を読んで下さい。
3.      Have a look at the eg/ directory in the Hibernate distribution, it contains a simple standalone application. Copy your JDBC driver to the lib/ directory and editetc/hibernate.properties, specifying correct values for your database. From a command prompt in the distribution directory, type ant eg (using Ant), or under Windows, typebuild eg.
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 Hibernate in Action (http://www.manning.com/bauer) 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 for Hibernate in Action.
このリファレンスドキュメントを第1の情報源として使ってください。 もしアプリケーション設計のさらなる情報が必要だったり、 ステップ・バイ・ステップのチュートリアルの方がお好みなら、 Hibernate in Action (http://www.manning.com/bauer) を読むことを考えてください。 またhttp://caveatemptor.hibernate.orgに来てHibernate in Action 例題アプリケーションをダウンロードしてみてください。
5.      FAQs are answered on the Hibernate website.
HibernateのウェブサイトにFAQがあります。
6.      Third party demos, examples, and tutorials are linked on the Hibernate website.
サードパーティのデモ、例、チュートリアルがHibernateのウェブサイトからリンクされています。
7.      The Community Area on the Hibernate website is a good resource for design patterns and various integration solutions (Tomcat, JBoss AS, Struts, EJB, etc.).
Hibernateウェブサイトのコミュニティ・エリアは、 デザインパターンやいろいろな統合ソリューション Tomcat, JBoss, Spring, Struts, EJBなど)のよい情報源です。
If you have questions, use the user forum linked on the Hibernate website. We also provide a JIRA issue trackings system for bug reports and feature requests. If you are interested in the development of Hibernate, join the developer mailing list. If you are interested in translating this documentation into your language, contact us on the developer mailing list.
質問があれば、Hibernateウェブサイトからリンクされている、ユーザ・フォーラムを使ってください。 またバグレポートと機能要求のために、JIRA議題トラッキング・システムを用意しています。 もしHibernateの開発に興味があれば、開発者メーリングリストに参加してください。 もしこのドキュメントのあなたの言語への翻訳に興味があれば、 開発者メーリングリストで私たちに連絡してください。
Commercial development support, production support, and training for Hibernate is available through JBoss Inc. (see http://www.hibernate.org/SupportTraining/). Hibernate is a Professional Open Source project and a critical component of the JBoss Enterprise Middleware System (JEMS) suite of products.
Hibernateの商業的な開発のサポート、製品サポート、トレーニングはJBoss Inc.を通して利用できます。 (http://www.hibernate.org/SupportTraining/を見てください。)HibernateJBoss Professional Open Sourceプロダクト・スイートのプロジェクトです。
Chapter 1. Introduction to Hibernate(1章:Hibernateの紹介)
1.1.      Preface(序文)
This chapter is an introductory tutorial for new users of Hibernate. We start with a simple command line application using an in-memory database and develop it in easy to understand steps.
この章はHibernateを初めて使うユーザ向けの入門的なチュートリアルです。インメモリデータベースを使う簡単なコマンドラインアプリケーションから始め、 一歩一歩わかりやすいやり方で開発を進めます。
This tutorial is intended for new users of Hibernate but requires Java and SQL knowledge. It is based on a tutorial by Michael Gloegl, the third-party libraries we name are for JDK 1.4 and 5.0. You might need others for JDK 1.3.
このチュートリアルはHibernateを初めて使うユーザを想定していますが、理解するにはJavaSQLについての知識が必要です。これはMichael Gloeglの手によるチュートリアルを下敷きにしていますが、ここでサードパーティライブラリと言っているのは、JDK 1.45.0用のものです。JDK 1.3を利用するのであれば他のライブラリが必要かもしれません。
The source code for the tutorial is included in the distribution in thedoc/reference/tutorial/ directory.
チュートリアルのソースコードはHibernateディストリビューションのdoc/reference/tutorial/にあります。
1.2.      Part 1 - The first Hibernate Application(初めてのHibernateアプリケーション)
First, we'll create a simple console-based Hibernate application. We use an Java database (HSQL DB), so we do not have to install any database server.
最初にコンソールベースの簡単なHibernateアプリケーションを作成します。Javaデータベース(HSQL DB)を利用するので、データベースサーバをインストールする必要はありません。
Let's assume we need a small database application that can store events we want to attend, and information about the hosts of these events.
仮に小さなデータベースアプリケーションが必要だとしましょう。そのアプリケーションには出席したいイベントと、そのイベントのホストについての情報を格納するものとします。
The first thing we do, is set up our development directory and put all the Java libraries we need into it. Download the Hibernate distribution from the Hibernate website. Extract the package and place all required libraries found in /lib into into the /libdirectory of your new development working directory. It should look like this:
最初にすることは開発用のディレクトリをセットアップして、必要となるすべてのJavaライブラリを配置することです。HibernateウェブサイトからHibernateディストリビューションをダウンロードしてください。ファイルを解凍して /libにある必要なライブラリのすべてを、新しい開発用ディレクトリの/libディレクトリに配置してください。このようになっているはずです:
+lib
  antlr.jar
  cglib.jar
  asm.jar
  asm-attrs.jars
  commons-collections.jar
  commons-logging.jar
  hibernate3.jar
  jta.jar
  dom4j.jar
  log4j.jar 
This is the minimum set of required libraries (note that we also copied hibernate3.jar, the main archive) for Hibernate at the time of writing. The Hibernate release you are using might require more or less libraries. See the README.txt file in the lib/ directory of the Hibernate distribution for more information about required and optional third-party libraries. (Actually, Log4j is not required but preferred by many developers.)
これが本ドキュメント執筆時点でのHibernateの必要最低限のライブラリです(メインアーカイブのhibernate3.jarもコピーしていることに注意してください)。Hibernateのバージョンによってはさらに必要なライブラリや、不要なライブラリがあるかもしれません。Hibernateディストリビューションのlib/ディレクトリにある README.txtファイルを見てください。必須またはオプションのサードパーティライブラリについての情報を載せています。(実際Log4jは必須ではありませんが、多くの開発者が好んでいます)。
Next we create a class that represents the event we want to store in database.
次にデータベースに格納するイベントを表すクラスを作成します。
1.2.1.               The first class(最初のクラス)
Our first persistent class is a simple JavaBean class with some properties:
最初の永続クラスは、プロパティをいくつか持つシンプルなJavaBeanです:
package events;

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;
    }
}
You can see that this class uses standard JavaBean naming conventions for property getter and setter methods, as well as private visibility for the fields. This is a recommended design - but not required. Hibernate can also access fields directly, the benefit of accessor methods is robustness for refactoring. The no-argument constructor is required to instantiate an object of this class through reflection.
ご覧のとおり、このクラスはフィールドがprivateの可視性を持っているのと同時に、JavaBean標準のゲッター、セッターメソッドの命名規約に従っています。このような設計は推奨されていますが必須ではありません。アクセサメソッドを設けるのはリファクタリングを考えた頑健性のためで、Hibernateはフィールドに直接アクセスすることも可能です。引数のないコンストラクタは、リフレクションでこのクラスのインスタンスを作成するために必要です。
The id property holds a unique identifier value for a particular event. All persistent entity classes (there are less important dependent classes as well) will need such an identifier property if we want to use the full feature set of Hibernate. In fact, most applications (esp. web applications) need to distinguish objects by identifier, so you should consider this a feature rather than a limitation. However, we usually don't manipulate the identity of an object, hence the setter method should be private. Only Hibernate will assign identifiers when an object is saved. You can see that Hibernate can access public, private, and protected accessor methods, as well as (public, private, protected) fields directly. The choice is up to you and you can match it to fit your application design.
idプロパティは、ある特定のイベントに対するユニークな識別子の値を保持します。Hibernateの完全な機能を使いたければ、すべての永続エンティティクラス(それほど重要ではない依存クラスというものもあります)にこのような識別子プロパティが必要になります。事実上ほとんどのアプリケーション(特にwebアプリケーション)では、識別子でオブジェクトを区別する必要があるため、これは制限というよりも特徴であると考えるべきです。しかし通常オブジェクトのIDを操作するようなことはしません。そのためセッターメソッドはprivateにするべきです。Hibernateだけがオブジェクトがセーブされたときに識別子へ値を代入します。Hibernateが(public, private, protected)フィールドに直接アクセスできるのと同様に、public, private, protectedのアクセサメソッドにアクセスできるということがわかるでしょう。選択はあなたに任されているので、あなたのアプリケーションの設計に合わせることができます。
The no-argument constructor is a requirement for all persistent classes; Hibernate has to create objects for you, using Java Reflection. The constructor can be private, however, package visibility is required for runtime proxy generation and efficient data retrieval without bytecode instrumentation.
引数のないコンストラクタはすべての永続クラスに必須です。これはHibernateJavaのリフレクションを使って、オブジェクトを作成しなければならないためです。コンストラクタをprivateにすることは可能ですが、実行時のプロキシ生成と、バイトコード操作なしの効率的なデータの抽出には、package可視性が必要です。
Place this Java source file in a directory called src in the development folder, and in its correct package. The directory should now look like this:
開発フォルダのsrcというディレクトリの適切なパッケージに、このJavaソースファイルを配置してください。この時点でディレクトリは以下のようになっているはずです:
.
+lib
  <Hibernate and third-party libraries>
+src
  +events
    Event.java
In the next step, we tell Hibernate about this persistent class.
次のステップでは、Hibernateにこの永続クラスの情報を教えます。
1.2.2.               The mapping file(マッピングファイル)
Hibernate needs to know how to load and store objects of the persistent class. This is where the Hibernate mapping file comes into play. The mapping file tells Hibernate what table in the database it has to access, and what columns in that table it should use.
Hibernateは、どのように永続クラスのオブジェクトをロードし格納すればよいかを知る必要があります。ここでHibernateマッピングファイルが登場します。マッピングファイルは、データベース内のどのテーブルにアクセスしなければならないか、そのテーブルのどのカラムを使うべきかを、Hibernateに教えます。
The basic structure of a mapping file looks like this:
マッピングファイルの基本的な構造はこのようになります:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
[...]
</hibernate-mapping>
Note that the Hibernate DTD is very sophisticated. You can use it for auto-completion of XML mapping elements and attributes in your editor or IDE. You also should open up the DTD file in your text editor - it's the easiest way to get an overview of all elements and attributes and to see the defaults, as well as some comments. Note that Hibernate will not load the DTD file from the web, but first look it up from the classpath of the application. The DTD file is included in hibernate3.jar as well as in the src/ directory of the Hibernate distribution.
Hibernate DTDが非常に洗練されていることに注目してください。このDTDは、エディタやIDEでのXMLマッピング要素と属性のオートコンプリーション機能に利用できます。またDTDファイルをテキストエディタで開けてみてください。というのも、すべての要素と属性を概観し、コメントやデフォルトの値を見るには一番簡単な方法だからです。Hibernateは、webからDTDファイルをロードせずに、まずアプリケーションのクラスパスからこれを探し出そうとすることに注意してください。DTDファイルはHibernateディストリビューションsrc/ディレクトリと同様、hibernate3.jarにも含まれています。
We will omit the DTD declaration in future examples to shorten the code. It is of course not optional.
以降の例ではコードを短くするためにDTD宣言を省略します。当然ですがこれはオプションではありません。
Between the two hibernate-mapping tags, include a class element. All persistent entity classes (again, there might be dependent classes later on, which are not first-class entities) need such a mapping, to a table in the SQL database:
2つのhibernate-mappingタグの間にclass要素を含めてください。すべての永続エンティティクラス(念を押しますが、ファーストクラスのエンティティではない依存クラスというものが後ほど登場します)はSQLデータベース内のテーブルへのこのようなマッピングを必要とします。
<hibernate-mapping>

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

    </class>

</hibernate-mapping>
So far we told Hibernate how to persist and load object of class Event to the tableEVENTS, each instance represented by a row in that table. Now we continue with a mapping of the unique identifier property to the tables primary key. In addition, as we don't want to care about handling this identifier, we configure Hibernate's identifier generation strategy for a surrogate primary key column:
これまで私たちは、EventクラスのオブジェクトをEVENTSテーブルに対して、どのように永続化したりロードしたりするのかをHibernateに教えてきました。そして個々のインスタンスはテーブルの行として表現されます。それでは引き続きテーブルの主キーに対するユニークな識別子プロパティをマッピングしていきます。さらに、この識別子の扱いに気を使いたくなかったのと同様に、代理の主キーカラムに対するHibernateの識別子生成戦略を設定します。
<hibernate-mapping>

    <class name="events.Event" table="EVENTS">
        <id name="id" column="EVENT_ID">
            <generator class="native"/>
        </id>
    </class>

</hibernate-mapping>
The id element is the declaration of the identifer property, name="id" declares the name of the Java property - Hibernate will use the getter and setter methods to access the property. The column attribute tells Hibernate which column of the EVENTS table we use for this primary key. The nested generator element specifies the identifier generation strategy, in this case we used native, which picks the best strategy depending on the configured database (dialect). Hibernate supports database generated, globally unique, as well as application assigned identifiers (or any strategy you have written an extension for).
id要素は識別子プロパティの宣言であり、name="id"Javaプロパティの名前を宣言します。Hibernateはこのプロパティへアクセスするためにゲッター、セッターメソッドを使います。カラム属性ではEVENTSテーブルのどのカラムを主キーとして使うのかをHibernateに教えます。入れ子になっているgenerator要素は、識別子を生成する時の戦略を指定します。(この例ではnativeを用いました)。この要素は、設定したデータベース(dialect)に対する最良な識別子生成戦略を選定するものです。Hibernateは、アプリケーションで値を割り当てる戦略(もしくは独自に拡張した戦略)と同様に、グローバルにユニークな値をデータベースに生成させる戦略もサポートしています。
Finally we include declarations for the persistent properties of the class in the mapping file. By default, no properties of the class are considered persistent:
最後にクラスの永続プロパティの宣言をマッピングファイルに含めます。デフォルトでは、クラスのプロパティは永続と見なされません:
<hibernate-mapping>

    <class name="events.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>
Just as with the id element, the name attribute of the property element tells Hibernate which getter and setter methods to use. So, in this case, Hibernate will look forgetDate()/setDate(), as well as getTitle()/setTitle().
id要素の場合と同様に、property要素の name属性で、どのゲッターとセッターメソッドを使うべきかをHibernateに教えます。この例では、HibernategetDate()/setDate()getTitle()/setTitle()を探します。
Why does the date property mapping include the column attribute, but the title doesn't? Without the column attribute Hibernate by default uses the property name as the column name. This works fine for title. However, date is a reserved keyword in most database, so we better map it to a different name.
なぜdateプロパティのマッピングにはcolumn属性があり、titleプロパティにはないのでしょうか?column属性がなければ、Hibernateはプロパティ名をカラム名として使います。これはtitleでは上手く行きます。しかしdateはほとんどのデータベースで予約語なので、違う名前でマッピングした方がよいのです。
The next interesting thing is that the title mapping also lacks a type attribute. The types we declare and use in the mapping files are not, as you might expect, Java data types. They are also not SQL database types. These types are so called Hibernate mapping types, converters which can translate from Java to SQL data types and vice versa. Again, Hibernate will try to determine the correct conversion and mapping type itself if the type attribute is not present in the mapping. In some cases this automatic detection (using Reflection on the Java class) might not have the default you expect or need. This is the case with the date property. Hibernate can't know if the property (which is of java.util.Date) should map to a SQL datetimestamp, or time column. We preserve full date and time information by mapping the property with a timestampconverter.
次に興味深いのはtitleマッピングがtype属性をも欠いている点です。マッピングファイルで宣言して使うtypeは、おわかりかもしれませんがJavaのデータ型ではありません。SQLデータベースの型でもありません。これはHibernateマッピング型と呼ばれる、JavaからSQLデータの型へまたはSQLからJavaデータ型へ翻訳するコンバータです。繰り返しになりますが、Hibernatetype属性がマッピングファイル内になければ、正しいコンバージョンとマッピング型を自分で解決しようとします。(Javaクラスのリフレクションを使った)この自動検知は、場合によってはあなたが期待または必要とするデフォルト値にならないかもしれません。dateプロパティの場合がそうでした。Hibernateはこの(java.util.Dateの)プロパティをSQLdate,timestamp, timeのうち、どのカラムにマッピングするべきなのかわかりません。timestampコンバータでプロパティをマッピングすることにより、完全な日時を保存します。
This mapping file should be saved as Event.hbm.xml, right in the directory next to theEvent Java class source file. The naming of mapping files can be arbitrary, however thehbm.xml suffix is a convention in the Hibernate developer community. The directory structure should now look like this:
このマッピングファイルは、Event.hbm.xmlとしてEventJavaクラスソースファイルのすぐ隣にセーブするべきです。マッピングファイルの命名方法は任意ですが、hbm.xmlサフィックスがHibernateの開発者のコミュニティ内での習慣となっています。現在ディレクトリ構造は以下のようになっているはずです。
.
+lib
  <Hibernate and third-party libraries>
+src
  +events
    Event.java
    Event.hbm.xml
We continue with the main configuration of Hibernate.
Hibernateの主要な設定を続けます。
1.2.3.          Hibernate configuration(Hibernateの設定)
We now have a persistent class and its mapping file in place. It is time to configure Hibernate. Before we do this, we will need a database. HSQL DB, a java-based SQL DBMS, can be downloaded from the HSQL DB website. Actually, you only need thehsqldb.jar from this download. Place this file in the lib/ directory of the development folder.
ここまでで永続クラスとマッピングファイルが揃いました。これからHibernateの設定を行いますが、その前にデータベースが必要です。HSQL DBJavaベースのインメモリSQL DBMSであり、HSQL DBウェブサイトからダウンロードできます。実際にはダウンロードした中のhsqldb.jarだけが必要です。このファイルを開発フォルダのlib/ディレクトリに配置してください。
Create a directory called data in the root of the development directory - this is where HSQL DB will store its data files. Now start the database by running java -classpath ../lib/hsqldb.jar org.hsqldb.Server in this data directory. You can 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 HSQL DB (press CTRL + C in the window), delete all files in the data/ directory, and start HSQL DB again.
dataというディレクトリを開発ディレクトリのルートに作成してください。HSQL DBはここにデータファイルを格納します。このデータディレクトリにおいてjava -classpath lib/hsqldb.jar org.hsqldb.Serverを実行し、データベースを起動させてください。動作の開始と、TCP/IPソケットのバインドが確認できます。後ほど作成するアプリケーションはここに接続します。もしこのチュートリアル中にデータベースを初期化したければ、HSQL DBをシャットダウンして(作業ウィンドウでCTRL + Cを押します)data/ディレクトリ内のファイルを全て消去した後、HSQL DBを再起動します。
Hibernate is the layer in your application which connects to this database, so it needs connection information. The connections are made through a JDBC connection pool, which we also have to configure. The Hibernate distribution contains several open source JDBC connection pooling tools, but will use the Hibernate built-in connection pool for this tutorial. Note that you have to copy the required library into your classpath and use different connection pooling settings if you want to use a production-quality third party JDBC pooling software.
Hibernateはアプリケーションのデータベースに接続する層なので、コネクションの情報が必要になります。コネクションはJDBCコネクションプールを通じて行われますが、これも設定する必要があります。HibernateディストリビューションにはいくつかのオープンソースのJDBCコネクションプールツールが含まれていますが、このチュートリアルではHibernateに組み込まれたコネクションプールを使います。もし製品レベルの品質のサードパーティJDBCコネクションプールソフトウェアを使いたければ、クラスパスに必要なライブラリをコピーして、異なるコネクションプールを設定しなければならないことに注意してください。
For Hibernate's configuration, we can use a simple hibernate.properties file, a slightly more sophisticated hibernate.cfg.xml file, or even complete programmatic setup. Most users prefer the XML configuration file:
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://hibernate.sourceforge.net/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">create</property>

        <mapping resource="events/Event.hbm.xml"/>

    </session-factory>

</hibernate-configuration>
Note that this XML configuration uses a different DTD. We configure Hibernate'sSessionFactory - a global factory responsible for a particular database. If you have several databases, use several <session-factory> configurations, usually in several configuration files (for easier startup).
このXMLの設定が異なるDTDを使うことに注意してください。特定のデータベースを受け持つグローバルファクトリであるHibernateSessionFactoryを設定します。もし複数のデータベースがある場合には、(スタートアップを簡単にするため)通常いくつかの設定ファイル内で、いくつかのsession-factoryを使う設定にしてください
The first four property elements contain the necessary configuration for the JDBC connection. The dialect property element specifies the particular SQL variant Hibernate generates. Hibernate's automatic session management for persistence contexts will come in handy as you will soon see. The hbm2ddl.auto option turns on automatic generation of database schemas - directly into the database. This can of course also be turned off (by removing the config option) or redirected to a file with the help of theSchemaExport Ant task. Finally, we add the mapping file(s) for persistent classes to the configuration.
最初の4つのproperty要素はJDBCコネクションに必要な設定を含んでいます。dialectという名前のproperty要素は、Hibernateが生成する特定のSQL方言を指定します。永続的なコンテキストに対するHibernateのセッションの自動管理は、後の例ですぐにわかるように、役に立つことでしょう。hbm2ddl.autoオプションはデータベーススキーマの自動生成をonにします。これは直接データベースに対して生成されます。当然(configオプションを削除して)offにしたり、SchemaExportというAntタスクの助けを借りてファイルにリダイレクトしたりできます。最後に永続クラスのためのマッピングファイルを設定に追加します。
Copy this file into the source directory, so it will end up in the root of the classpath. Hibernate automatically looks for a file called hibernate.cfg.xml in the root of the classpath, on startup.
このファイルをソースディレクトリにコピーしてください。するとこれはクラスパスのルートにあることになります。Hibernateは、スタートアップ時にクラスパスのルートでhibernate.cfg.xmlというファイルを自動的に探します。
1.2.4.          Building with Ant(Antによるビルド)
We'll now build the tutorial with Ant. You will need to have Ant installed - get it from the Ant download page. How to install Ant will not be covered here. Please refer to theAnt manual. After you have installed Ant, we can start to create the buildfile. It will be called build.xml and placed directly in the development directory.
それではAntを使ってチュートリアルをビルドしましょう。それにはAntがインストールされていなければなりません。Antダウンロードページ(http://ant.apache.org/bindownload.cgi)からダウンロードしてください。Antのインストール方法はここでは説明しませんので、Antマニュアル(http://ant.apache.org/manual/index.html)を参照してください。Antをインストールすれば、ビルドファイルの作成を開始できます。このファイルはbuild.xmlと呼ばれ、開発ディレクトリに直接配置します。
A basic build file looks like this:
基本的なビルドファイルはこのようになります
<project name="hibernate-tutorial" default="compile">

    <property name="sourcedir" value="${basedir}/src"/>
    <property name="targetdir" value="${basedir}/bin"/>
    <property name="librarydir" value="${basedir}/lib"/>

    <path id="libraries">
        <fileset dir="${librarydir}">
            <include name="*.jar"/>
        </fileset>
    </path>

    <target name="clean">
        <delete dir="${targetdir}"/>
        <mkdir dir="${targetdir}"/>
    </target>

    <target name="compile" depends="clean, copy-resources">
      <javac srcdir="${sourcedir}"
             destdir="${targetdir}"
             classpathref="libraries"/>
    </target>

    <target name="copy-resources">
        <copy todir="${targetdir}">
            <fileset dir="${sourcedir}">
                <exclude name="**/*.java"/>
            </fileset>
        </copy>
    </target>

</project>
This will tell Ant to add all files in the lib directory ending with .jar to the classpath used for compilation. It will also copy all non-Java source files to the target directory, e.g. configuration and Hibernate mapping files. If you now run Ant, you should get this output:
これは.jarで終わるlibディレクトリのすべてのファイルを、コンパイルに使用するクラスパスに追加することをAntに教えます。また、Javaソースファイルでないすべてのファイルをターゲットディレクトリにコピーするということでもあります。例えば設定ファイルやHibernateマッピングファイルなどです。今Antを実行すると、このような出力があるはずです
C:\hibernateTutorial\>ant
Buildfile: build.xml

copy-resources:
     [copy] Copying 2 files to C:\hibernateTutorial\bin

compile:
    [javac] Compiling 1 source file to C:\hibernateTutorial\bin

BUILD SUCCESSFUL
Total time: 1 second 
1.2.5.          Startup and helpers(スタートアップとヘルパ)
It's time to load and store some Event objects, but first we have to complete the setup with some infrastructure code. We have to startup Hibernate. This startup includes building a global SessionFactory object and to store it somewhere for easy access in application code. A SessionFactory can open up new Session's. A Session represents a single-threaded unit of work, the SessionFactory is a thread-safe global object, instantiated once.
さてEventオブジェクトをロードしたり格納したりする準備ができました。しかしまずはインフラストラクチャのコードを書いて、セットアップを完了する必要があります。まずはHibernateをスタートアップしなければなりません。このスタートアップには、グローバルのSessionFactoryオブジェクトを生成して、それをアプリケーションのコードでアクセスしやすい場所に格納することが含まれます。SessionFactoryは新しくSessionをオープンすることができます。Sessionはシングルスレッドの作業単位(Unit of Work)を表現します。それに対しSessionFactoryはスレッドセーフのグローバルオブジェクトであり、一度だけインスタンス化されます。
We'll create a HibernateUtil helper class which takes care of startup and makes accessing a SessionFactory convenient. Let's have a look at the implementation:
ここでスタートアップを行い、 便利にSessionFactoryへアクセスするHibernateUtilヘルパクラスを作成します。 実装を見てみましょう。
package util;

import org.hibernate.*;
import org.hibernate.cfg.*;

public class HibernateUtil {

    private static final SessionFactory sessionFactory;

    static {
        try {
            // Create the SessionFactory from hibernate.cfg.xml
            sessionFactory = 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;
    }

}
This class does not only produce the global SessionFactory in its static initializer (called once by the JVM when the class is loaded), but also hides the fact that it uses a static singleton. It might as well lookup the SessionFactory from JNDI in an application server.
このクラスは静的初期化ブロック(クラスがロードされるときにJVMによって一度だけ呼ばれる)でグローバルのSessionFactoryを生成するだけではなく、静的シングルトンの使用を隠蔽します。アプリケーションサーバーのJNDIからSessionFactoryをルックアップするのと同様です。
If you give the SessionFactory a name in your configuration file, Hibernate will in fact try to bind it to JNDI after it has been built. To avoid this code completely you could also use JMX deployment and let the JMX-capable container instantiate and bind aHibernateService to JNDI. These advanced options are discussed in the Hibernate reference documentation.
設定ファイル内でSessionFactoryに名前を与えると、HibernateSessionFactory構築後にJNDIに対しバインドを行おうとします。このコードを完全に排除するためには、JMXデプロイメントを利用してJMXを利用できるコンテナをインスタンス化し、HibernateServiceJNDIへバインドすることもできます。これらの高度なオプションは、Hibernateのリファレンスドキュメントで説明されています。
Place HibernateUtil.java in the development source directory, in a package next toevents:
HibernateUtil.javaを開発ソースディレクトリにあるeventsパッケージの隣に配置してください。
.
+lib
  <Hibernate and third-party libraries>
+src
  +events
    Event.java
    Event.hbm.xml
  +util
    HibernateUtil.java
  hibernate.cfg.xml
+data
build.xml
This should again compile without problems. We finally need to configure a logging system - Hibernate uses commons logging and leaves you the choice between Log4j and JDK 1.4 logging. Most developers prefer Log4j: copy log4j.properties from the Hibernate distribution (it's in the etc/ directory) to your src directory, next to hibernate.cfg.xml. Have a look at the example configuration and change the settings if you like to have more verbose output. By default, only Hibernate startup message are shown on stdout.
これは問題なく再コンパイルできるはずです。最後にロギングシステムを設定する必要があります。Hibernatecommons loggingを使うため、Log4jJDK 1.4 loggingの選択をする必要がありません。ほとんどの開発者が好むのはLog4jです。Hibernateディストリビューション(のetc/ディレクトリ)から log4j.propertiesをあなたのsrcディレクトリ内のhibernate.cfg.xmlの隣にコピーしてください。設定例を見て、冗長な出力がよければ設定を変更してください。デフォルトではHibernateのスタートアップメッセージだけが標準出力に表示されます。
The tutorial infrastructure is complete - and we are ready to do some real work with Hibernate.
チュートリアルのインフラは完全です。Hibernateを使って実際の作業をする準備が整いました。
1.2.6.          Loading and storing objects(オブジェクトのロードと格納)
Finally, we can use Hibernate to load and store objects. We write an EventManager class with a main() method:
ついにオブジェクトのロードと格納にHibernateを使うことができます。main()メソッドを持つEventManagerクラスを書きます:
package events;
import org.hibernate.Session;

import java.util.Date;

import 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();
    }

}
We create a new Event object, and hand it over to Hibernate. Hibernate now takes care of the SQL and executes INSERTs on the database. Let's have a look at the Session andTransaction-handling code before we run this.
新しいEventオブジェクトを生成し、それをHibernateに渡します。今ではHibernateSQLを処理し、データベースでINSERTを実行します。実行前にSessionTransactionを処理するコードを確認してください。
Session is a single unit of work. For now we'll keep things simple and assume a one-to-one granularity between a Hibernate Session and a database transaction. To shield our code from the actual underlying transaction system (in this case plain JDBC, but it could also run with JTA) we use the Transaction API that is available on the Hibernate Session.
Session1つの作業単位(Unit of Work)です。当分の間、話を簡単にするために、SessionTransactionの対応を一対一と仮定します。使用しているトランザクション・システム(このケースではJTAと共存できる単純なJDBC)からコードを保護するために、HibernateSession上で利用可能なTransactionAPIを使用します。
What does sessionFactory.getCurrentSession() do? First, you can call it as many times and anywhere you like, once you get hold of your SessionFactory (easy thanks toHibernateUtil). The getCurrentSession() method always returns the "current" unit of work. Remember that we switched the configuration option for this mechanism to "thread" in hibernate.cfg.xml? Hence, the current unit of work is bound to the current Java thread that executes our application. However, this is not the full picture, you also have to consider scope, when a unit of work begins and when it ends.
sessionFactory.getCurrentSession()はなにをするのでしょうか?まず、いったんSessionFactoryを取得し保持すれば(HibernateUtilのおかげで簡単です)、このメソッドを何度でも、どこからでも呼び出すことが出来ます。getCurrentSession()メソッドは常に「現在の」作業単位(Unit of Work)を返します。hibernate.cfg.xmlのこの機能の設定で、"thread"を指定したことを思い出してください。このため現在の作業単位のスコープは、このアプリケーションを実行する現在のJavaスレッドです。しかしこれで全てではありません。Sessionは最初に必要となったとき、つまり最初にgetCurrentSession()が呼ばれたときに開始します。そのときHibernateにより現在のスレッドに結び付けられます。トランザクションが終了(コミットもしくはロールバック)したとき、HibernateもスレッドからSessionを切り離し、クローズします。再びgetCurrentSession()を呼ぶと、新しいSessionを取得して新しい作業単位をスタートできます。このthread-boundプログラミング・モデルはHibernateを利用する上で最も人気があります。
Session begins when it is first needed, when the first call to getCurrentSession() is made. It is then bound by Hibernate to the current thread. When the transaction ends, either through commit or rollback, Hibernate automatically unbinds the Session from the thread and closes it for you. If you call getCurrentSession() again, you get a newSession and can start a new unit of work. This thread-bound programming model is the most popular way of using Hibernate, as it allows flexible layering of your code (transaction demarcation code can be separated from data access code, we'll do this later in this tutorial).
最初にこれが必要なときにgetCurrentSession()を呼ばれるときに始まります。それでこれが有効なスレッドでHibernateからバウンドされます。トランザクションが終わるとHibernateがスレッドからSessionをアンバウンドし、これを終了します。もし、getCurrentSession()をもう一回呼ばれたら、新しいSessionGetし、新しいユニットを開始します。このスレッドバウンドプログラミングモデルはHibernateを使うもっとも一般的な方法であり、コードを階層化して許可します。(トランザクション分離コードはデータアクセスコードとは違って、これについてこのチュートリアルで後ほど説明します。)
Related to the unit of work scope, should the Hibernate Session be used to execute one or several database operations? The above example uses one Session for one operation. This is pure coincidence, the example is just not complex enough to show any other approach. The scope of a Hibernate Session is flexible but you should never design your application to use a new Hibernate Session for every database operation. So even if you see it a few more times in the following (very trivial) examples, consider session-per-operation an anti-pattern. A real (web) application is shown later in this tutorial.
作業範囲と関係しますが、Hibernate Sessionは一つまたはいくつかのデータベースをオペレーション使用できるでしょうか?上記に挙げた例は一つのオペレーションのために一つのSessionを使用します。これが適切なものであり、上記の例は、他のアプローチを示すのに複雑ではありません。Hibernate Sessionの範囲は柔軟ではありますが、各データベースのオペレーションのために新しいHibernate Sessionを使ってアプリケーションをデザインすることはできません。上記の例で複数回使用したい場合は、アンチパターンのSession per-operationを考慮して下さい。これを使った(Web)アプリケーションは後ほどこのチュートリアルにあげていきます。
Have a look at Chapter 11, Transactions And Concurrency for more information about transaction handling and demarcation. We also skipped any error handling and rollback in the previous example.
トランザクションの扱いと境界の詳しい情報については、Chapter 11, Transactions And Concurrencyを見てください。この例ではエラー処理やロールバックも割愛します。
To run this first routine we have to add a callable target to the Ant build file:
この最初のルーチンを実行するには、Antのビルドファイルに呼び出し可能なターゲットを追加しなければなりません:
<target name="run" depends="compile">
    <java fork="true" classname="events.EventManager" classpathref="libraries">
        <classpath path="${targetdir}"/>
        <arg value="${action}"/>
    </java>
</target>
The value of the action argument is set on the command line when calling the target:
action引数の値は、ターゲットを呼ぶときにコマンドラインで設定します:
C:\hibernateTutorial\>ant run -Daction=store
You should see, after compilation, Hibernate starting up and, depending on your configuration, lots of log output. At the end you will find the following line:
コンパイルすると、Hibernateがスタートし、あなたの設定によりますが、多くのログ出力があるはずです。その最後には以下の行があるでしょう:
[java] Hibernate: insert into EVENTS (EVENT_DATE, title, EVENT_ID) values (?, ?, ?)
This is the INSERT executed by Hibernate, the question marks represent JDBC bind parameters. To see the values bound as arguments, or to reduce the verbosity of the log, check your log4j.properties.
これはHibernateが実行するINSERTで、クエスチョンマークはJDBCバインドパラメータを表しています。引数としてバインドされる値を見るため、あるいはログの冗長性を減らすためには、log4j.propertiesをチェックしてください。
Now we'd like to list stored events as well, so we add an option 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());
    }
}
We also add a new listEvents() method:
新しいlistEvents()メソッドも追加します。
private List listEvents() {

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

    session.beginTransaction();

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

    session.getTransaction().commit();

    return result;
}
What we do here is use an HQL (Hibernate Query Language) query to load all existingEvent 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, of course.
ここですることは、データベースから存在するすべてのEventオブジェクトをロードするHQL (Hibernate Query Language) クエリを使うことです。Hibernateは適切なSQLを生成し、それをデータベースに送り、そのデータを使ってEventオブジェクトを生成します。当然HQLでさらに複雑なクエリを作成できます。
Now, to execute and test all of this, follow these steps:
以下のステップで、すべての実行とテストを行います。
?         Run ant run -Daction=store to store something into the database and, of course, to generate the database schema before through hbm2ddl.
?         hbm2ddlを通す前にデータベースのデータを作成し、データベーススキーマを生成するために、ant run -Daction=storeを実行してください。
?         Now disable hbm2ddl by commenting out the property in your hibernate.cfg.xmlfile. Usually you only leave it turned on in continous unit testing, but another run of hbm2ddl would drop everything you have stored - the create configuration setting actually translates into "drop all tables from the schema, then re-create all tables, when the SessionFactory is build".
?         今はhibernate.cfg.xmlファイルのプロパティをコメントアウトしてhbm2ddlを無効にしてください。通常は継続的に単体テストをしている間はhbm2ddlを有効にしておくのですが、それ以外の場合にhbm2ddlを起動すると格納しておいた全てのデータをドロップするでしょう。設定をcreateにすると、結果としてSessionFactory生成の際、スキーマから全てのテーブルをドロップして再作成する」という設定になります。
If you now call Ant with -Daction=list, you should see the events you have stored so far. You can of course also call the store action a few times more.
-Daction=listと指定してAntを呼ぶと、これまで格納したイベントが見えるはずです。storeアクションを数回以上呼ぶことも可能です。
Note: Most new Hibernate users fail at this point and we see questions about Table not found error messages regularly. However, if you follow the steps outlined above you will not have this problem, as hbm2ddl creates the database schema on the first run, and subsequent application restarts will use this schema. If you change the mapping and/or database schema, you have to re-enable hbm2ddl once again.
注意:初めてHibernateに触れる人々の多くがここで失敗するため、Table not foundエラーメッセージに関する質問を定期的に見かけます。しかし上記のステップに従えば、hbm2ddlが最初に実行されたときにデータベーススキーマを作成し、その後の実行においてもこのスキーマを使用するので、問題は起こらないでしょう。マッピングやデータベーススキーマを変更したときは、もう一度hbm2ddlを有効にしてください。
1.3.      Part 2 - Mapping associations(パート2 - 関連のマッピング)
We mapped a persistent entity class to a table. Let's build on this and add some class associations. First we'll add people to our application, and store a list of events they participate in.
永続エンティティクラスをテーブルにマッピングしました。さらにこの上にいくつかのクラスの関連を追加しましょう。まず初めにアプリケーションに人々を追加し、彼らが参加するイベントのリストを格納します。
1.3.1.          Mapping the Person class(Personクラスのマッピング)
The first cut of the Person class is simple:
最初のPersonクラスは単純です:
package events;

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'

}
Create a new mapping file called Person.hbm.xml (don't forget the DTD reference at the top):
Person.hbm.xmlという新しいマッピングファイルを作成してください(ファイルの最初にDTDへの参照を忘れずに入れてください):
<hibernate-mapping>

    <class name="events.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>
Finally, add the new mapping to Hibernate's configuration:
最後にHibernateの設定に新しいマッピングを追加してください。
<mapping resource="events/Event.hbm.xml"/>
<mapping resource="events/Person.hbm.xml"/>
We'll now create an association between these two entities. Obviously, persons can participate in events, and events have participants. The design questions we have to deal with are: directionality, multiplicity, and collection behavior.
それではこれら2つのエンティティ間の関連を作成します。人々がイベントに参加でき、イベントが参加者を持つのは明らかです。扱わなければならない設計の問題は、方向、多重度、コレクションの振る舞いです。
1.3.2.          A unidirectional Set-based association(単方向Setベース関連)
We'll add a collection of events to the Person class. That way we can easily navigate to the events for a particular person, without executing an explicit query - by callingaPerson.getEvents(). We use a Java collection, a Set, because the collection will not contain duplicate elements and the ordering is not relevant for us.
イベントのコレクションをPersonクラスに追加します。こうしておくと、明示的なクエリ、つまりわざわざaPerson.getEvents()を呼び出さずに、特定の人に紐付くイベントを簡単にナビゲートすることができます。私たちはJavaのコレクション、Setを使います。コレクションは重複要素を持たないし、順番は私たちには意味がないからです。
We need a unidirectional, many-valued associations, implemented with a Set. Let's write the code for this in the Java classes and then map it:
Setで実装される単方向、多値関連が必要です。Javaクラス内に対応するコードを書いてマッピングしましょう。
public class Person {

    private Set events = new HashSet();

    public Set getEvents() {
        return events;
    }

    public void setEvents(Set events) {
        this.events = events;
    }
}
Before we map this association, think about the other side. Clearly, we could just keep this unidirectional. Or, we could create another collection on the Event, if we want to be able to navigate it bi-directional, i.e. anEvent.getParticipants(). This is not necessary, from a functional perspective. You could 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, we call this a many-to-many association. Hence, we use Hibernate's many-to-many mapping:
この関連をマッピングする前に、反対側について考えてください。明らかなことですが、今はこれを単方向にしただけです。逆に、Event側にも別のコレクションを作ることもできます。例えばanEvent.getParticipants()のように、双方向にナビゲートしたければ、そうすることもできます。これは機能的にみて必要ではありません。特定のイベントに関係するデータを取得する明確なクエリを、いつでも実行することが出来ました。この設計の選択は開発者に任されていて、この議論により明らかなのは関連の多重度です。つまり両側を「many」値にする、多対多と呼ばれる関連です。そのためHibernatemany-to-manyマッピングを使います:
<class name="events.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="events.Event"/>
    </set>

</class>
Hibernate supports all kinds of collection mappings, a <set> being most common. For a many-to-many association (or n:m entity relationship), an association table is needed. Each row in this table represents a link between a person and an event. The table name is configured with the table attribute of the set element. The identifier column name in the association, for the person's side, is defined with the <key> element, the column name for the event's side with the column attribute of the <many-to-many>. You also have to tell Hibernate the class of the objects in your collection (correct: the class on the other side of the collection of references).
Hibernateはありとあらゆる種類のコレクションマッピングをサポートしていますが、最も一般的なものがsetです。多対多関連(またはn:mエンティティリレーションシップ)には、関連テーブルが必要です。このテーブルのそれぞれの行は、人とイベント間のリンクを表現します。テーブル名はset要素のtable属性で設定します。人側の関連の識別子カラム名はkey要素で、イベント側のカラム名はmany-to-manycolumn属性で定義します。Hibernateにコレクションのオブジェクトのクラス(正確には、参照のコレクションの反対側のクラス)を教えなければなりません。
The database schema for this mapping is therefore:
そのためこのマッピングのデータベーススキーマは以下のようになります。:
    _____________        __________________
   |             |      |                  |       _____________
   |   EVENTS    |      |   PERSON_EVENT   |      |             |
   |_____________|      |__________________|      |    PERSON   |
   |             |      |                  |      |_____________|
   | *EVENT_ID   | <--> | *EVENT_ID        |      |             |
   |  EVENT_DATE |      | *PERSON_ID       | <--> | *PERSON_ID  |
   |  TITLE      |      |__________________|      |  AGE        |
   |_____________|                                |  FIRSTNAME  |
                                                  |  LASTNAME   |
                                                  |_____________|

1.3.3.          Working the association(関連を働かせる)
Let's bring some people and events together in a new method in EventManager:
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. As you can see, 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, and you can also try it by modifying the name or the date property of any of your objects. As long as they are in persistentstate, that is, bound to a particular Hibernate Session (i.e. they have been just loaded or saved in a unit of work), 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 - as defined by the threadconfiguration option for the CurrentSessionContext class.
PersonEventをロードした後、普通のコレクションメソッドを使って単純にそのコレクションを修正してください。ご覧のとおりupdate()save()の明示的な呼び出しはありません。Hibernateは、修正されたことにより更新する必要のあるコレクションを自動的に検知します。これは自動ダーティチェックと呼ばれ、オブジェクトの名前やdateプロパティを修正することで試すことも可能です。それらが永続状態にある限り、つまり特定のHibernateSessionにバインドされている限り(例えば作業単位(Unit of Work)の中で単にロードまたはセーブされた)、Hibernateはどんな変更もモニターし、遅延書き込み(write-behind)SQLを実行します。通常、作業単位(Unit of Work)の最後にだけ行われるデータベースとメモリの状態を同期させる処理は、フラッシュと呼ばれます。このコードでは、作業単位(Unit of Work)はデータベーストランザクションのコミット(もしくはロールバック)で終了します。これは、CurrentSessionContextクラスに対してthreadを設定したためです。
You might of course load person and event in different units of work. Or you modify an object outside of a Session, when it is not in persistent state (if it was persistent before, we call this state detached). You can even modify a collection when it is detached:
異なる作業単位(Unit of Work)で人々とイベントをロードすることも当然できます。そうでなければ、永続状態にないとき(以前に永続であったなら、この状態を分離(detached)と呼びます)、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();
}
The call to update makes a detached object persistent again, you could say it binds it to a new unit of work, so any modifications you made to it while detached can be saved to the database. This includes any modifications (additions/deletions) you made to a collection of that entity object.
updateの呼び出しは分離オブジェクトを再び永続化します。これは、新しい作業単位(Unit of Work)にバインドすると言えるでしょう。そのため分離の間に加えられたどのような修正もデータベースにセーブできます。エンティティオブジェクトのコレクションへの修正(追加・削除)も同様にセーブできます。
Well, this is not much use in our current situation, but it's an important concept you can design into your own application. For now, complete this exercise by adding a new action to the EventManager's main method and call it from the command line. If you need the identifiers of a person and an event - the save() method returns it (you might have to modify some of the previous methods to return that identifier):
これ、今はあまり使いみちがありませんが、自分のアプリケーションの設計に組み込むことができる重要なコンセプトです。それではこのエクササイズの最後に、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);
This was an example of an association between two equally important classes, two entities. As mentioned earlier, there are other classes and types in a typical model, usually "less important". Some you have already seen, like an int or a String. We call these classes value types, and their instances depend on a particular entity. Instances of these types don't have their own identity, nor are they shared between entities (two persons don't reference the same firstname object, even if they have the same first name). Of course, value types can not only be found in the JDK (in fact, in a Hibernate application all JDK classes are considered value types), but you can also write dependent classes yourself, Address or MonetaryAmount, for example.
これは同じように重要な2つのクラス、つまり2つのエンティティ間の関連の例でした。前に述べたように、典型的なモデルには、普通「比較的重要ではない」他のクラスと型があります。これまでに見たようなintStringのようなものです。このようなクラスを値型と言います。このインスタンスは特定のエンティティに依存します。この型のインスタンスは独自のIDを持ちませんし、エンティティ間で共有されることもありません(ファーストネームが同じだったとしても、2人の人は同じfirstnameオブジェクトを参照しません)。値型はもちろんJDK内に見つかりますが、それだけではなく(実際、HibernateアプリケーションにおいてすべてのJDKクラスは値型と見なせます)、例えばAddressMonetaryAmountのような独自の依存クラスを書くこともできます。
You can also design a collection of value types. This is conceptually very different from a collection of references to other entities, but looks almost the same in Java.
値型のコレクションを設計することもできます。これは他のエンティティへの参照のコレクションとは概念的に非常に異なりますが、Javaではほとんど同じように見えます。
1.3.4.          Collection of values(値のコレクション)
We add a collection of value typed objects to the Person entity. We want to store email addresses, so the type we use is String, and the collection is again a Set:
値型オブジェクトのコレクションをPersonエンティティへ追加します。Eメールアドレスを格納したいのですが、String型を使っているのでコレクションは再びSetです:
private Set emailAddresses = new HashSet();

public Set getEmailAddresses() {
    return emailAddresses;
}

public void setEmailAddresses(Set emailAddresses) {
    this.emailAddresses = emailAddresses;
}
The mapping of this Set:
<set name="emailAddresses" table="PERSON_EMAIL_ADDR">
    <key column="PERSON_ID"/>
    <element type="string" column="EMAIL_ADDR"/>
</set>
The difference compared with the earlier mapping is the element part, which tells Hibernate that the collection does not contain references to another entity, but a collection of elements of type String (the lowercase name tells you it's a Hibernate mapping type/converter). Once again, the table attribute of the set element determines the table name for the collection. The key element defines the foreign-key column name in the collection table. The column attribute in the element element defines the column name where the String values will actually be stored.
前のマッピングと比べて違うのはelementの部分ですが、Hibernateにこのコレクションが他のエンティティへの参照を含まず、String型の要素のコレクションを含むことを教えます。(小文字の名前(string)Hibernateのマッピング型またはコンバータであるということです)。繰り返しますが、set要素のtable属性は、コレクションのためのテーブル名を指定します。key要素はコレクションテーブルの外部キーカラム名を定義します。element要素のcolumn属性はStringの値が実際に格納されるカラムの名前を定義します。
Have a look at the updated schema:
更新したスキーマを確認してください:

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

You can see that the primary key of the collection table is in fact a composite key, using both columns. This also implies that there can't be duplicate email addresses per person, which is exactly the semantics we need for a set in Java.
コレクションテーブルの主キーは、実際は両方のカラムを使った複合キーであることがわかります。これは人ごとにEメールアドレスが重複できないということで、Javasetに要求されるセマンティクスそのものです。
You can now try and add elements to this collection, just like we did before by linking persons and events. It's the same code in Java:
以前人とイベントを関連づけたときと全く同じように、今や試しにコレクションに要素を追加することができるようになりました。両方ともJavaでは同じコードです。
private void addEmailToPerson(Long personId, String emailAddress) {

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

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

    // The getEmailAddresses() might trigger a lazy load of the collection
    aPerson.getEmailAddresses().add(emailAddress);

    session.getTransaction().commit();
}
This time we didnt' use a fetch query to initialize the collection. Hence, the call to its getter method will trigger an additional select to initialize it, so we can add an element to it. Monitor the SQL log and try to optimize this with an eager fetch.
今回、コレクションの初期化にfetchクエリを使用しませんでした。そのため、getterメソッドの呼び出しによってコレクションを初期化するためのSELECTが実行されるので、コレクションに要素を追加できます。SQLのログを監視して、即時フェッチを使って最適化してください。
1.3.5.          Bi-directional associations(双方向関連)
Next we are going to map a bi-directional association - making the association between person and event work from both sides in Java. Of course, the database schema doesn't change, we still have many-to-many multiplicity. A relational database is more flexible than a network programming language, so it doesn't need anything like a navigation direction - data can be viewed and retrieved in any possible way.
次に双方向関連をマッピングします。Javaで両側から人とイベントの関連を動作させます。もちろん、データベーススキーマは変わりませんが、多重度は多対多のままです。リレーショナルデータベースはネットワークプログラミング言語よりも柔軟なので、ナビゲーションの方向のようなものを必要としません。データはあらゆるの方法で見たり復元できるということです。
First, add a collection of participants to the Event Event class:
まずEventイベントクラスに参加者のコレクションを追加します:
private Set participants = new HashSet();

public Set getParticipants() {
    return participants;
}

public void setParticipants(Set participants) {
    this.participants = participants;
}
Now map this side of the association too, in Event.hbm.xml.
それではEvent.hbm.xmlで関連のこちら側をマッピングしてください。
<set name="participants" table="PERSON_EVENT" inverse="true">
    <key column="EVENT_ID"/>
    <many-to-many column="PERSON_ID" class="events.Person"/>
</set>
As you see, these are normal set mappings in both mapping documents. Notice that the column names in key and many-to-many are swapped in both mapping documents. The most important addition here is the inverse="true" attribute in the set element of theEvent's collection mapping.
ご覧のとおり、いずれのマッピングドキュメント(XMLファイル)でも、普通のsetマッピングを使っています。keymany-to-manyのカラム名が、両方のマッピングドキュメントで入れ替えになっていることに注目してください。ここで最も重要な追加項目は、Eventのコレクションマッピングのset要素にあるinverse="true"属性です。
What this means is that Hibernate should take the other side - the Person class - when it needs to find out information about the link between the two. This will be a lot easier to understand once you see how the bi-directional link between our two entities is created .
この指定の意味は、2つの間のエンティティ間のリンクについての情報を探す必要があるとき、Hibernateは反対側のエンティティ、つまりPersonクラスから探すということです。一度2つのエンティティ間の双方向リンクがどのように作成されるかがわかれば、これを理解することはとても簡単です。
1.3.6.          Working bi-directional links(双方向リンクの動作)
First, keep in mind that Hibernate does not affect normal Java semantics. How did we create a link between a Person and an Event in the unidirectional example? We added an instance of Event to the collection of event references, of an instance of Person. So, obviously, if we want to make this link working bi-directional, we have to do the same on the other side - adding a Person reference to the collection in an Event. This "setting the link on both sides" is absolutely necessary and you should never forget doing it.
まず、Hibernateが通常のJavaのセマンティクスに影響を及ぼさないことを心に留めておいてください。私たちは、単方向の例としてどのようにPersonEventの間のリンクを作成したでしょうか?Personのインスタンスのイベントへの参照のコレクションにEventのインスタンスを追加しました。そのためこのリンクを双方向にしたければ、当たり前ですが反対側にも同じことをしなければなりません。EventのコレクションにPersonへの参照を追加するということです。この「両側でリンクを設定すること」は絶対に必要なので、決して忘れないでください。
Many developers program defensive and create a link management methods to correctly set both sides, e.g. in 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);
}
Notice that the get and set methods for the collection are now protected - this allows classes in the same package and subclasses to still access the methods, but prevents everybody else from messing with the collections directly (well, almost). You should probably do the same with the collection on the other side.
コレクションのゲットとセットメソッドが現在protectedになっていることに注意してください。これは同じパッケージのクラスやサブクラスのメソッドは依然アクセスが可能ですが、(ほとんど)そのパッケージ外のどのクラスでも直接そのコレクションを台無しにすることを防ぎます。おそらく反対側のコレクションにも同じことをした方がいいでしょう。
What about the inverse mapping attribute? For you, and for Java, a bi-directional link is simply a matter of setting the references on both sides correctly. Hibernate however doesn't have enough information to correctly arrange SQL INSERT and UPDATEstatements (to avoid constraint violations), and needs some help to handle bi-directional associations properly. Making one side of the association inverse tells Hibernate to basically ignore it, to consider it a mirror of the other side. That's all that is necessary for Hibernate to work out all of the issues when transformation a directional navigation model to a SQL database schema. The rules you have to remember are straightforward: All bi-directional associations need one side as inverse. In a one-to-many association it has to be the many-side, in many-to-many association you can pick either side, there is no difference.
inverseマッピング属性とはいったい何でしょうか?開発者とJavaにとっては、双方向リンクは単に両側の参照を正しく設定するということです。しかしHibernateは(制約違反を避けるために)SQLINSERTUPDATE文を正確に変更するための十分な情報を持っていないので、双方向関連プロパティを扱うための何らかの助けを必要とします。関連の片側をinverseに設定することで、Hibernateは基本的には設定した側を無視し、反対側の鏡として考えます。これだけで、Hibernateは方向を持つナビゲーションモデルをSQLデータベーススキーマへ変換するときのすべての問題にうまく対処できます。覚えておかなければならないルールは簡単です。双方向関連は必ず片側をinverseにする必要があるということです。一対多関連ではそれは多側でなければなりません。多対多関連ではどちら側でも構いません。どちらでも違いはありません。
Let's turn this into a small web application.
ではこれを小さなWebアプリケーションにしてみましょう。
1.4.      Part 3 - The EventManager web application(パート3 - EventManager Webアプリケーション)
A Hibernate web application uses Session and Transaction almost like a standalone application. However, some common patterns are useful. We now write anEventManagerServlet. This servlet can list all events stored in the database, and it provides an HTML form to enter new events.
HibernateWebアプリケーションは、スタンドアローンのアプリケーションのようにSessionTransactionを使用します。しかしいくつかの一般的なパターンが役立ちます。ここでEventManagerServletを作成します。このサーブレットは、データベースに格納した全てのイベントをリストにでき、さらにHTMLフォームから新しいイベントを入力できるものです。
1.4.1. Writing the basic servlet(基本的なServletの記述)
Create a new class in your source directory, in the events package:
新しいクラスを、ソースディレクトリのeventsパッケージに作成してください。
package events;

// Imports

public class EventManagerServlet extends HttpServlet {

    // Servlet code
}
The servlet handles HTTP GET requests only, hence, the method we implement isdoGet():
ServletHTTPGETリクエストのみを処理するので、doGet()を実装します。
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();
        throw new ServletException(ex);
    }

}
The pattern we are applying here is called session-per-request. When a request hits the servlet, a new Hibernate Session is opened through the first call to getCurrentSession()on the SessionFactory. Then a database transaction is started--all data access as to occur inside a transaction, no matter if data is read or written (we don't use the auto-commit mode in applications).
これはsession-per-requestというパターンです。Servletがリクエストを受け取ると、SessionFactorygetCurrentSession()の最初の呼び出しで、Hibernateの新しいSessionが開かれます。そのときデータベーストランザクションが開始されます。データの読み書きに関わらず、すべてのデータアクセスはトランザクション内で行います。(アプリケーション内ではオートコミットモードを使用しません)。
Do not use a new Hibernate Session for every database operation. Use one HibernateSession that is scoped to the whole request. Use getCurrentSession(), so that it is automatically bound to the current Java thread.
各データベース操作のために新しいHibernate Sessionを使用しないで下さい。すべてのRequestを含む一つのHibernate Sessionを使用してください。getCurrentSession()を使用すれば、現在のJavaスレッドに自動的にバインドしてくれます。
Next, the possible actions of the request are processed and the response HTML is rendered. We'll get to that part soon.
次に、リクエストのアクションは処理され、レスポンスであるHTMLが描画されます。これについてはすぐに説明します。
Finally, the unit of work ends when processing and rendering is complete. If any problem occured during processing or rendering, an exception will be thrown and the database transaction rolled back. This completes the session-per-request pattern. Instead of the transaction demarcation code in every servlet you could also write a servlet filter. See the Hibernate website and Wiki for more information about this pattern, called Open Session in View--you'll need it as soon as you consider rendering your view in JSP, not in a servlet.
最後にリクエストの処理とHTML描画が完了したときに、作業単位(Unit of Work)を終了します。もし処理や描画中に問題が発生した場合、exceptionが投げられてデータベーストランザクションをロールバックします。これでsession-per-requestパターンが完了します。全てのサーブレットにトランザクション境界のコードを書く代わりに、サーブレットフィルタに記述することも可能です。Open Session in Viewと呼ばれるこのパターンについては、HibernateWebサイトやWikiを参照してください。サーブレットではなくJSPHTML描画をしようとすると、すぐにこのパターンについての情報が必要になるでしょう。
1.4.2. Processing and rendering(処理と描画)
Let's implement the processing of the request and rendering of the page.
では、リクエストの処理とページの描画を実装します。
// 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();
Granted, this coding style with a mix of Java and HTML would not scale in a more complex application--keep in mind that we are only illustrating basic Hibernate concepts in this tutorial. The code prints an HTML header and a footer. Inside this page, an HTML form for event entry and a list of all events in the database are printed. The first method is trivial and only outputs HTML:
JavaHTMLが混在するコーディングスタイルは、より複雑なアプリケーションには適していないでしょう(このチュートリアルでは、基本的な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>");
}
The listEvents() method uses the Hibernate Session bound to the current thread to execute a query:
listEvents()メソッドは、現在のスレッドに結びつくHibernateSessionを使用して、クエリを実行します。
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>");
        for (Iterator it = result.iterator(); 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>");
    }
}
Finally, the store action is dispatched to the createAndStoreEvent() method, which also uses the Session of the current thread:
最後に、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);
}
That's it, the servlet is complete. A request to the servlet will be processed in a singleSession and Transaction. As earlier in the standalone application, Hibernate can automatically bind these ojects to the current thread of execution. This gives you the freedom to layer your code and access the SessionFactory in any way you like. Usually you'd use a more sophisticated design and move the data access code into data access objects (the DAO pattern). See the Hibernate Wiki for more examples.
これでサーブレットの完成です。サーブレットへのリクエストは、一つのSessionTransactionで処理されるでしょう。最初のスタンドアローンのアプリケーションのように、Hibernateは自動的にこれらのオブジェクトを実行するスレッドに結び付けることができます。これにより、開発者が自由にコードをレイヤー分けでき、好きな方法でSessionFactoryへのアクセスができるようになります。通常、開発者はより洗練されたデザインを使用して、データアクセスのコードをデータアクセスオブジェクトに移動するでしょう(DAOパターン)。より多くの例は、HibernateWikiを参照してください。
1.4.3. Deploying and testing(デプロイとテスト)
To deploy this application you have to create a web archive, a WAR. Add the following Ant target to your build.xml:
このアプリケーションのデプロイのために、Webアーカイブ(WAR)を作成してください。以下のAntターゲットをbuild.xmlに加えてください。
<target name="war" depends="compile">
    <war destfile="hibernate-tutorial.war" webxml="web.xml">
        <lib dir="${librarydir}">
          <exclude name="jsdk*.jar"/>
        </lib>

        <classes dir="${targetdir}"/>
    </war>
</target>
This target creates a file called hibernate-tutorial.war in your project directory. It packages all libraries and the web.xml descriptor, which is expected in the base directory of your project:
このターゲットはhibernate-tutorial.warというファイルをプロジェクトディレクトリに作成します。このファイルはすべてのライブラリと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>events.EventManagerServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>Event Manager</servlet-name>
        <url-pattern>/eventmanager</url-pattern>
    </servlet-mapping>
</web-app>
Before you compile and deploy the web application, note that an additional library is required: jsdk.jar. This is the Java servlet development kit, if you don't have this library already, get it from the Sun website and copy it to your library directory. However, it will be only used for compliation and excluded from the WAR package.
Webアプリケーションのコンパイルとデプロイの前に、jsdk.jarという追加のライブラリが必要なことに注意してください。これはJavaサーブレットの開発キットです。もしまだこのライブラリを持っていないなら、Sunのウェブサイトで入手して、ライブラリディレクトリにコピーしてください。しかし、これはコンパイルにのみ使用され、WARパッケージからは除外されます。
To build and deploy call ant war in your project directory and copy the hibernate-tutorial.war file into your Tomcat webapp directory. If you don't have Tomcat installed, download it and follow the installation instructions. You don't have to change any Tomcat configuration to deploy this application though.
ビルドとデプロイのために、プロジェクトディレクトリでant warを呼び出し、hibernate-tutorial.warファイルをTomcatwebappディレクトリにコピーしてください。まだTomcatをインストールしていなければ、ダウンロードして、以下のインストールガイドに従ってください。しかし、このアプリケーションのデプロイするために、Tomcatの設定を変更する必要はありません。
Once deployed and Tomcat is running, access the application athttp://localhost:8080/hibernate-tutorial/eventmanager. Make sure you watch the Tomcat log to see Hibernate initialize when the first request hits your servlet (the static initializer in HibernateUtil is called) and to get the detailed output if any exceptions occurs.
一度デプロイしてTomcatを起動すれば、http://localhost:8080/hibernate-tutorial/eventmanagerでアプリケーションへのアクセスが可能です。最初のリクエストが作成したサーブレットに渡ったときに、TomcatのログでHibernateの初期化処理を確認してください(HibernateUtil内の静的初期化ブロックが呼ばれています)。また、exceptionが発生したなら詳細を確認してください。
1.5.      Summary(要約)
This tutorial covered the basics of writing a simple standalone Hibernate application and a small web application.
このチュートリアルでは、簡単なスタンドアローンのHibernateアプリケーションと小規模のWebアプリケーションを書くための基本を紹介しました。
If you already feel confident with Hibernate, continue browsing through the reference documentation table of contents for topics you find interesting - most asked are transactional processing (Chapter 11, Transactions And Concurrency), fetch performance (Chapter 19, Improving performance), or the usage of the API (Chapter 10, Working with objects) and the query features (Section 10.4, "Querying").
もうHibernateに自信があれば、リファレンスドキュメントの目次に目を通して、面白そうだと思うトピックを探してください。最も頻繁に質問があるのは、トランザクション処理(Chapter 11, Transactions And Concurrency)、フェッチのパフォーマンス(Chapter 19, Improving performance)、APIの使い方(Chapter 10, Working with objects)とクエリ(Section 10.4, "Querying")です。
Don't forget to check the Hibernate website for more (specialized) tutorials.
さらに(特別な)チュートリアルが必要なら、Hibernateウェブサイトを忘れずにチェックしてください。

No comments:

Post a Comment