Menu Close

Red Hat Training

A Red Hat training course is available for Red Hat JBoss Web Server

第2章 チュートリアル

本章は、インメモリデータベースを使用した簡単なアプリケーションから始まり、 Hibernate を段階的に説明する新規ユーザー向けの章です。 本チュートリアルは Michael Gloegl 氏が開発したチュートリアルよりも前のものを基にしています。 すべてのコードはプロジェクトソースの tutorials/web ディレクトリに格納されています。

重要

本チュートリアルは、 Java と SQL の知識があることを前提としています。 Java や SQL の知識に乏しい場合は、 これらの技術に関する知識を深めてから Hibernate について学ぶようにしてください。

注記

ディストリビューションの tutorial/eg プロジェクトソースディレクトリには他のサンプルアプリケーションも格納されています。

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

この例では、参加したいイベントやイベントのホストに関する情報を保存するための小さなデータベースアプリケーションを設定します。

注記

どのデータベースをご利用いただいても構いませんが、ここでは HSQLDB (インメモリの Java データベース) を使用し、特定のデータベースサーバーのインストールや設定に関する説明を省略します。

2.1.1. 設定

最初に、 開発環境を設定する必要があります。 ここでは、 Maven など、 多くのビルドツールが推奨する「標準レイアウト」を使用します。 Maven にこの レイアウト を詳細に説明するリソースがあります。 このチュートリアルはWebアプリケーションであるため、src/main/java ディレクトリや src/main/resources ディレクトリ、 src/main/webapp ディレクトリを使用します。
本チュートリアルではMavenを使っており、遷移従属性の管理機能や多くのIDE機能を活用し、Maven記述子を元にプロジェクトを自動設定しています。
<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>
  <packaging>war</packaging>
  <name>First Hibernate Tutorial</name>
  <build>
<!--we dont want the version to be part of the generated war file name-->
  <finalName>${artifactId}</finalName>
<!--we dont want to use the jars maven provided, we want to use JBoss' ones-->
  <plugins>
    <plugin>
      <artifactId>maven-war-plugin</artifactId>
      <configuration>
        <packagingExcludes>WEB-INF/lib/*.jar</packagingExcludes>
      </configuration>
    </plugin>
  </plugins>

  </build>
    <dependencies> 
      <dependency> 
      <groupId>org.hibernate</groupId> 
      <artifactId>hibernate-core</artifactId> 
      <version>3.3.2.GA_CP03</version>
<!-- please check the release notes for the correct version you're using --> 
    </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> 
      <version>2.5</version>
    </dependency> 
<!-- Hibernate uses slf4j for logging, for our purposes here use the simple backend --> 
    <dependency> 
      <groupId>org.slf4j</groupId> 
      <artifactId>slf4j-simple</artifactId> 
      <version>1.5.8</version> 
    </dependency> 
<!-- Hibernate gives you a choice of bytecode providers between cglib and javassist --> 
    <dependency> 
      <groupId>javassist</groupId> 
      <artifactId>javassist</artifactId> 
      <version>3.12.0.GA</version> 
    </dependency> 
  </dependencies> 
</project>

注記

Maven の使用は必須ではありません。 Ant など別の技術を使用して本チュートリアルをビルドする場合でもレイアウトは同じになります。 手作業で必要な従属性すべてに対応する必要があることのみが異なります。 Ivy を使用して遷移的従属性の管理を提供する場合でも、 下記の従属性を使用します。 下記の従属性を使用しない場合、 明示的従属性と遷移的従属性をすべて見つけ、 プロジェクトのクラスパスに追加する必要があります。 Hibernate ディストリビューションバンドルから作業する場合、 hibernate3.jarlib/required ディレクトリの全アーチファクト、 lib/bytecode/cglib ディレクトリまたは lib/bytecode/javassist ディレクトリの全ファイルが対象となります。 また、 servlet-api jar と slf4j ロギングバックエンドの 1 つが必要となります。
このファイルを pom.xml としてプロジェクトルートディレクトリに保存します。

2.1.2. 最初のクラス

次にデータベースに格納するイベントを表すクラスを作成します。 これは、 一部のプロパティを持つ簡単な JavaBean クラスになります。
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;
    }
}
このクラスは、 プロパティゲッターメソッドとセッタメソッドに対する標準の Java 命名規則やフィールドに対する private の可視性を使用します。 これが推奨設計となりますが、 必須ではありません。 Hibernate は直接フィールドにアクセスすることもでき、 アクセッサメソッドの利点は再ファクタリングの堅牢性になります。
id プロパティは、 特定イベントに対して固有の識別子の値を保持します。 Hibernate の機能を全て使用した場合、 すべての永続エントリクラス (それほど重要ではない依存クラスもあります) にこのような識別子プロパティが必要となります。 ほとんどのアプリケーション (特に Web アプリケーション) が識別子でオブジェクトを識別する必要があるため、 制限ではなく機能であると考えた方がよいでしょう。 しかし、 通常オブジェクトのアイデンティティは操作しないため、 セッタメソッドは private とするべきです。 オブジェクトが保存される時に Hibernate のみが識別子を割り当てます。 Hibernate は public、 private、 protected のアクセッサメソッドにアクセスでき、 public、 private、 protected のフィールドに直接アクセスできます。 選択は任意であるため、 アプリケーション設計にあわせて選択することができます。
引数のないコンストラクタはすべての永続クラスに必須です。Hibernate は Java Reflection を使用してオブジェクトを作成しなければなりません。コンストラクタを private にすることは可能ですが、ランタイム時にプロキシを生成し、バイトコードのインスツルメントなしで効率的にデータを読み出しするため、パッケージや public の可視性は必要となります。
このファイルを src/main/java/org/hibernate/tutorial/domain ディレクトリに保存します。

2.1.3. マッピングファイル

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

<hibernate-mapping package="org.hibernate.tutorial.domain">
[...]
</hibernate-mapping>
Hibernate DTD は非常に高機能です。 エディターや IDE の XML マッピング要素や属性を自動補完するために使用することができます。 要素や属性の全体を確認し、 デフォルトや一部コメントを閲覧するには、 テキストエディタで DTD ファイルを開くのが最も簡単な方法です。 Hibernate は Web より DTD ファイルをロードしませんが、 最初にアプリケーションのクラスパスより検索します。 DTD ファイルは hibernate-core.jar に含まれています (ディストリビューションバンドルを使用する場合は 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>
id 要素は識別子プロパティの宣言です。 name="id" マッピング属性が JavaBean プロパティの名前を宣言し、 プロパティのアクセスに getId() メソッドと setId() メソッドを使用するよう Hibernate に指示します。 column 属性は、 主キーの値を保持する EVENTS テーブルの列を Hibernate に伝えます。
ネストされた generator 要素は識別子生成戦略 (識別子の値を生成する方法) を指定します。この例では、 設定されたデータベース方言に応じて移植性のレベルを提供する native を選択しています。 Hibernate はデータベースによって生成され、グローバルに固有なアプリケーションによって割り当てられる識別子をサポートしています。識別子の値の生成は Hibernate の拡張ポイントの 1 つでもあり、 独自の戦略にプラグインすることができます。

注記

移植性という観点から考慮した場合、 native は最良の戦略とは見なされなくなりました。 詳細は 「識別子の生成」 を参照してください。
最後に、 残りのエンティティクラスプロパティに関して Hibernate に伝える必要があります。 デフォルトでは、 永続とされるクラスのプロパティはありません。
<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 属性がありません。 マッピングファイルで宣言して使用する型は Java のデータ型ではなく、 SQL のデータベース型でもありません。 これらの型は Hibernateマッピング型 と呼ばれ、 Java から SQ Lのデータ型または SQ Lから Java のデータ型に変換するコンバータになります。 type 属性がマッピングに存在しない場合は、 Hibernate が正しい変換とデータ型を判断します。 場合によっては、 Java クラス上の Reflection を使用した自動検出のデフォルトが必要なデフォルトでないことがあり、 date 属性がこれに該当します。 java.util.Date のプロパティが SQL の datetimestamptime 列のいずれかへマップするべきであることを Hibernate は認識しません。 完全な日付と時間の情報は、 このプロパティを timestamp コンバータでマッピングして保持されます。

注記

マッピングファイルが処理される時に Hibernate は Reflection を使用してこのマッピング型を判断します。 これには時間とリソースを要するため、 起動時のパフォーマンスが重要な場合は、 使用する型を明示的に定義した方がよいでしょう。
このマッピングファイルを src/main/resources/org/hibernate/tutorial/domain/Event.hbm.xml として保存します。

2.1.4. Hibernate の設定

この時点で永続クラスとそのマッピングファイルが設定されたはずです。 次に Hibernate を設定します。 最初に HSQLDB が「サーバーモード」で実行するよう設定します。

注記

これは、 実行の合間にデータを維持するために行います。
Maven の実行プラグインを使用して mvn exec:java -Dexec.mainClass="org.hsqldb.Server" -Dexec.args="-database.0 file:target/data/tutorial" を実行し、 HSQLDB サーバーを起動します。 これにより、 サーバーの起動とアプリケーションが後で接続する TCP/IP ソケットへのバインドを確認できます。 本チュートリアルの実行中に新たにデータベースを使用したい場合は、 HSQLDB をシャットダウンしてから target/data ディレクトリのファイルをすべて削除し、 HSQLDB を再度起動します。
アプリケーションの代わりに Hibernate がデータベースへ接続するため、 接続する方法を認識する必要があります。 本チュートリアルでは、 javax.sql.DataSource ではなくスタンドアロンの接続プールを使用します。 Hibernate は c3p0proxool の 2 つのサードバーティーによるオープンソース JDBC 接続プールをサポートしていますが、 本チュートリアルでは Hibernate にビルトインされている接続プールを使用します。

警告

Hibernate にビルトインされている接続プールは実稼働での使用には向いていません。
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">update</property>

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

    </session-factory>

</hibernate-configuration>

注記

この設定ファイルは異なる DTD を指定することに注意してください。
Hibernate のSessionFactory を設定します。 SessionFactory は特定のデータベースに対応するグローバルファクトリです。 複数のデータベースがある場合、 複数の設定ファイルに複数の <session-factory> 設定を使用するのが最も簡単です。
最初の 4 つの property 要素に JDBC 接続に必要な設定が含まれています。方言の property 要素は Hibernate が生成する SQL のバリアントを指定します。

注記

ほとんどの場合で Hibernate は使用する方言を正しく決定することができます。 詳細は 「方言の解決」 を参照してください。
永続コンテキストに対する Hibernate の自動管理は、 特にこのコンテキストで有用です。 hbm2ddl.auto オプションは、 データベーススキーマを直接データベースに自動生成する機能を有効にします。 設定オプションを削除するか、 SchemaExport Ant タスクでファイルをリダイレクトしてデータベーススキーマの自動生成を無効にすることもできます。 最後に、 永続クラスのマッピングファイルを設定に追加します。
このファイルを hibernate.cfg.xml として src/main/resources ディレクトリに保存します。

2.1.5. Maven によるビルド

Maven でチュートリアルをビルドします。 これには Maven をインストールする必要があります。 Maven は Maven ダウンロードページ よりダウンロードできます。 Maven はこれまでに作成した /pom.xml ファイルを読み取り、 基本的なプロジェクトタスクの一部を実行する方法を認識します。 最初に compile ゴールを実行し、 すべてをコンパイルできるようにします。
[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] ------------------------------------------------------------------------

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

Event オブジェクトの一部をロードしたり格納する準備ができましたが、 最初にインフラストラクチャコードで設定を完了する必要があります。 グローバルな org.hibernate.SessionFactory オブジェクトをビルドし、 アプリケーションコードで簡単にアクセスできるよう任意の場所に保存して Hibernate を起動する必要があります。 org.hibernate.Session インスタンスの取得には org.hibernate.SessionFactory を使用します。 org.hibernate.Session は単一スレッドの作業単位 (unit of work) を表します。 org.hibernate.SessionFactory は 1 度インスタンス化されるスレッドセーフのグローバルオブジェクトです。
起動やもっと簡単に 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;
    }

}
このコードを src/main/java/org/hibernate/tutorial/util/HibernateUtil.java として保存します。
このクラスは、 静的初期化子にグローバルな org.hibernate.SessionFactory 参照を作成するだけでなく、 静的なシングルトンを使用することを表に見せません。アプリケーションサーバーや他の場所の JNDI より org.hibernate.SessionFactory 参照をルックアップするのと同様です。
設定で org.hibernate.SessionFactory に名前を付ける場合、 Hibernate はビルドされた名前で JNDI へバインドしようとします。このような場合、 JMX デプロイメントを使用し、 JMX 対応のコンテナによって HibernateService を JNDI へインスタンス化しバインドする方法を使用した方がよいでしょう。 このような高度なオプションについては後ほど説明します。
ここでロギングシステムを設定する必要があります。 Hibernate は commons logging を使用し、 Log4j と JDK 1.4 ロギングの 2 つを選択できます。 開発者の多くは Log4j を選択します。 Log4j の場合、 etc/ ディレクトリにある Hibernate ディストリビューションの log4j.propertieshibernate.cfg.xml の隣の src ディレクトリへコピーします。 設定例よりも詳細な出力を希望する場合は、 設定を変更することができます。 デフォルトでは Hibernate 起動メッセージは標準出力 (stdout) で表示されます。
これでチュートリアルのインフラストラクチャが完成したため、 Hibernate を使って実際の作業を行う準備が整いました。

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

Hibernate を使って実際の作業を行う準備ができました。 最初に main() メソッドを持つ EventManager クラスを記述します。
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();
    }

}
createAndStoreEvent() に新しい Event オブジェクトが作成され、 Hibernate に渡されました。 この時点で Hibernate は SQL に対処し、 データベース上で INSERT を実行します。
org.hibernate.Session は単一の作業単位 (実行される単一のアトミックな作業) を表します。 ここでは、 分かりやすくするため Hibernate の org.hibernate.Session とデータベーストランザクション間の粒度を一対一とします。 実際に基礎となるトランザクションシステムからコードを保護するため、 Hibernate の org.hibernate.Transaction API を使用します。この例では JDBC ベースのトランザクションセマンティックを使用していますが、 JTA で実行することも可能です。
sessionFactory.getCurrentSession() は何を実行するのでしょうか。 org.hibernate.SessionFactory を取得した後、 どこでも何回でも呼び出すことができます。 getCurrentSession() メソッドは常に「現在」の作業単位を返します。 このメカニズムの設定オプションを src/main/resources/hibernate.cfg.xml の「スレッド」に切り替えたことを思い出してください。 この設定により、 現在の作業単位のコンテキストは、 アプリケーションを実行する現在の Java スレッドへバインドされます。

重要

Hibernate は現セッションの追跡に 3 つのメソッドを提供します。「スレッド」ベースのメソッドは実稼働の使用には向いておらず、 プロトタイプやチュートリアルのみに対して有用です。現セッションの追跡については後ほど詳しく説明します。
現在のスレッドに対して getCurrentSession() へ最初の呼び出しが実行された時に org.hibernate.Session が開始されます。 その後、 Hibernate によって現在のスレッドへバインドされます。 コミットやロールバックによってトランザクションが終了すると、 Hibernate はスレッドより自動的に org.hibernate.Session をアンバインドして閉じます。 getCurrentSession() を再度呼び出すと、 新しい org.hibernate.Session を取得し、 新しい作業単位 (unit of work) を開始することができます。
作業単位の範囲に関し、 Hibernate の org.hibernate.Session を使用して 1 つまたは複数のデータベース操作を実行するべきでしょうか。 前述の例では 1 つのorg.hibernate.Session を 1 つの操作に使用していますが、 これは単なる偶然です。 この例は単純であるため、 他の方法で表すことができないからです。 Hibernate の org.hibernate.Session の範囲は柔軟ですが、 データベース操作ごとに新しい Hibernate の org.hibernate.Session を使用しないようアプリケーションを設計するようにしてください。 次の例では 「操作毎のセッション」 が使用されていますが、 これはアンチパターンとして考慮するようにしてください。 本チュートリアルで後ほど使用する実際の Web アプリケーションを確認すると理解できるはずです。
トランザクションの処理と境界の詳細については、 12章トランザクションと並行性 を参照してください。 前の例ではエラー処理とロールバックを割愛しています。
mvn exec:java -Dexec.mainClass="org.hibernate.tutorial.EventManager" -Dexec.args="store" を実行し、 Maven 実行プラグインを使用して必要なクラスパスの設定を持つクラスを呼び出します。

注記

最初に mvn compile を実行する必要がある場合があります。
これで Hibernate が起動するはずです。また、設定によっては大量のログ出力が表示されることがあります。最後の方に、以下の行が表示されます。
[java] Hibernate: insert into EVENTS (EVENT_DATE, title, EVENT_ID) values (?, ?, ?)
これは Hibernate によって実行された INSERT になります。
格納されたイベントを一覧表示するには、 main メソッドにオプションを追加します。
        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;
    }
ここでは、 HQL (Hibernate Query Language) クエリを使用して、 データベースより既存の Event オブジェクトをすべてロードします。 Hibernate は適切な SQL を生成し、 データベースへ送信して Event オブジェクトにデータを追加します。 HQL でさらに複雑なクエリを作成することができます。 詳細は 15章HQL: Hibernate クエリ言語 を参照してください。
これで、 mvn exec:java -Dexec.mainClass="org.hibernate.tutorial.EventManager" -Dexec.args="list" を実行し、 Maven 実行プラグインを使用して新しい機能を呼び出せるようになりました。