blob: 4ae939d3dd3c007b96d73ec0c2dae7d9bcb7d3cd [file] [log] [blame]
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
= WebアプリケーションでのHibernateの使用
:jbake-type: tutorial
:jbake-tags: tutorials
:jbake-status: published
:icons: font
:syntax: true
:source-highlighter: pygments
:toc: left
:toc-title:
:description: WebアプリケーションでのHibernateの使用 - Apache NetBeans
:keywords: Apache NetBeans, Tutorials, WebアプリケーションでのHibernateの使用
このチュートリアルでは、NetBeans IDEを使用してデータをデータベースから表示するWebアプリケーションを作成してデプロイします。このWebアプリケーションでは、プレーン・オールドJavaオブジェクト(POJO)を取得してリレーショナル・データベースに保存するための持続性レイヤーとして、Hibernateフレームワークを使用します。
Hibernateは、ORM (object relational mapping)のためのツールを提供するフレームワークです。このチュートリアルでは、IDEHibernateフレームワークのサポートを追加し、必要なHibernateファイルを作成する方法を示します。Javaオブジェクトを作成し、Hibernateを使用するようにアプリケーションを構成した後、JSF管理対象Beanとデータを表示するJSF 2.0ページを作成します。
このチュートリアルを開始する前に、必要に応じて次のドキュメントをお読みください。
* link:http://www.hibernate.org/[+hibernate.org+]のHibernateドキュメント
* link:quickstart-webapps.html[+Webアプリケーション開発入門+]
* link:jsf20-intro.html[+JavaServer Faces 2.x入門+]
image::images/netbeans-stamp-74-73-72.png[title="このページの内容は、NetBeans IDE 7.2、7.3および7.4に適用されます"]
*このチュートリアルに従うには、次のソフトウェアとリソースが必要です。*
|===
|ソフトウェアまたはリソース |必須バージョン
|link:https://netbeans.org/downloads/index.html[+NetBeans IDE+] |7.1、7.2、7.3、7.4、Java EEバージョン
|link:http://www.oracle.com/technetwork/java/javase/downloads/index.html[+Java Development Kit (JDK)+] |バージョン6または7
|GlassFish Server Open Source Edition |3.xまたは4.x
|link:http://www.mysql.com/[+MySQLデータベース・サーバー+] |バージョン5.x
|Sakilaデータベース |更新センターから入手できるプラグイン
|===
link:https://netbeans.org/projects/samples/downloads/download/Samples/JavaEE/DVDStoreEE6.zip[+終了したプロジェクトのZIPアーカイブ+]はダウンロードできます。
== データベースの作成
このチュートリアルでは、MySQLのサイトで無償提供されているMySQLサンプル・データベースの ``sakila`` を使用します。IDEのインストールにはsakilaデータベースが含まれないため、チュートリアルを開始する前にデータベースを作成する必要があります。
sakilaデータベースを作成するには、プラグイン・マネージャを使用してSakilaサンプル・データベース・プラグインをダウンロードしてインストールできます。このプラグインをインストールすると、「MySQLデータベースの作成」ダイアログ・ボックスのデータベース・リストにsakilaデータベースが追加されます。
MySQLを操作するためのIDEの構成については、link:../ide/mysql.html[+MySQLデータベースへの接続+]のチュートリアルを参照してください。
1. プラグイン・マネージャを開き、Sakilaサンプル・データベース・プラグインをインストールします。
2. プラグインをインストールした後、「サービス」ウィンドウで「データベース」ノードを展開し、「MySQLサーバー」ノードを右クリックして「起動」を選択して、MySQLデータベースを起動します。
3. MySQLサーバー」ノードを右クリックし、「データベースを作成」を選択します。
4. MySQLデータベースの作成」ダイアログ・ボックスで「新規データベース名」ドロップダウン・リストから「Sakilaデータベース」を選択します。「OK」をクリックします。
image::images/create-sakila-mysql.png[title="「MySQLデータベースの作成」ダイアログのスクリーンショット"]
OK」をクリックすると、「MySQLサーバー」ノードの下に「Sakila」ノードが表示されます。
. Sakila」ノードを右クリックし、「接続」を選択します。
「接続」をクリックすると、「Sakila」データベースのデータベース接続のノード( ``jdbc:mysql://localhost:3306/sakila [デフォルトの_ユーザー名_]`` )が「データベース」ノードに一覧表示されます。接続が開いたら、接続ノードを展開してデータベースのデータを表示できます。
== Webアプリケーション・プロジェクトの作成
この課題では、Webアプリケーション・プロジェクトを作成し、Hibernateライブラリをそのプロジェクトに追加します。プロジェクトを作成する場合は、新規プロジェクト・ウィザードの「フレームワーク」パネルで「Hibernate」を選択してデータベースを指定します。
1. メイン・メニューから「ファイル」>「新規プロジェクト」([Ctrl]-[Shift]-[N]、Macの場合は[⌘]-[Shift]-[N])を選択します。「Java Web」カテゴリから「Webアプリケーション」を選択し、「次」をクリックします。
2. プロジェクト名として「*DVDStore*」と入力し、プロジェクトの場所を設定します。
3. 専用フォルダを使用するオプションが選択されている場合は選択を解除します。「次」をクリックします。
このチュートリアルでは、ライブラリを他のユーザーと共有する必要がないため、プロジェクト・ライブラリを専用のフォルダにコピーする理由はほとんどありません。
. サーバーを「GlassFish Server」に設定し、「Java EEバージョン」を「Java EE 6 Web」または「Java EE 7 Web」に設定します。「次」をクリックします。
. JavaServer Faces」チェックボックスを選択し、デフォルトのJSF 2.xライブラリを使用します。
. フレームワークの選択リストで「Hibernate」チェックボックスを選択します。
. 「データベース接続」ドロップダウン・リストから「Sakilaデータベース」を選択します。「終了」をクリックします。
*注意:* Sakilaデータベースがウィザードの「フレームワーク」パネルのオプションとして使用できない場合、この接続が「サービス」ウィンドウの「データベース」ノードに一覧表示されているかどうかを確認します。ここに接続がない場合、データベース接続を作成する必要があります。
image::images/hib-newwebapp.png[title="プロジェクトへのHibernateサポートの追加を示す新規プロジェクト・ウィザードの「フレームワーク」パネル"]
「終了」をクリックすると、Webアプリケーション・プロジェクトが作成され、 ``hibernate.cfg.xml`` ファイルと ``index.xhtml`` がエディタに表示されます。
「プロジェクト」ウィンドウの「ライブラリ」ノードを展開すると、IDEによってHibernateライブラリがそのプロジェクトに追加されたことを確認できます。
image::images/hib-libraries.png[title="Hibernateライブラリが表示された「プロジェクト」ウィンドウのスクリーンショット"]
== Hibernate構成ファイルの変更
Hibernateフレームワークを使用する新規プロジェクトを作成する場合、IDEでは ``hibernate.cfg.xml`` 構成ファイルがアプリケーションのコンテキスト・クラスパスのルート(「ファイル」ウィンドウの ``src/java`` )に自動的に作成されます。ファイルは、「プロジェクト」ウィンドウの「ソース・パッケージ」の下の ``<デフォルト・パッケージ>`` にあります。構成ファイルには、データベース接続、リソース・マッピング、およびその他の接続プロパティに関する情報が格納されます。このファイルは、マルチビュー・エディタを使用して編集、または直接XMLエディタでXMLを編集できます。
この課題では、 ``hibernate.cfg.xml`` に指定されたデフォルトのプロパティを編集し、SQL文のデバッグ・ロギングを有効にし、Hibernateのセッション・コンテキスト管理を有効にします。
1. 「デザイン」タブで ``hibernate.cfg.xml`` を開きます。このファイルは、「プロジェクト」ウィンドウで「ソース・パッケージ」の下の ``<デフォルト・パッケージ>`` ノードを展開し、 ``hibernate.cfg.xml`` をダブルクリックすることで開きます。
2. マルチビューXMLエディタで、「オプションのプロパティ」の下の「構成プロパティ」ノードを展開します。
3. 「追加」をクリックして「Hibernateのプロパティの追加」ダイアログ・ボックスを開きます。
4. このダイアログ・ボックスで、「 ``hibernate.show_sql`` 」プロパティを選択し、値を「 ``true`` 」に設定します。これにより、SQL文のデバッグ・ロギングが有効になります。
image::images/add-property-showsql.png[title="hibernate.show_sqlプロパティの設定値が表示された「Hibernateのプロパティの追加」ダイアログ・ボックス"]
. Miscellaneous Properties」ノードを展開し、「追加」をクリックします。
. このダイアログ・ボックスで「 ``hibernate.current_session_context_class`` 」プロパティを選択し、値を「 ``thread`` 」に設定すると、Hibernateの自動セッション・コンテキスト管理が有効になります。
image::images/add-property-sessioncontext.png[title="hibernate.current_session_context_classプロパティの設定値が表示された「Hibernateのプロパティの追加」ダイアログ・ボックス"]
. 「その他のプロパティ」ノードの下の「追加」を再度クリックし、「プロパティ名」ドロップダウン・リストで ``hibernate.query.factory_class`` を選択します。
. 「プロパティ値」として「*org.hibernate.hql.classic.ClassicQueryTranslatorFactory*」を選択します。「OK」をクリックします。
image::images/add-property-factoryclass.png[title="hibernate.query.factory_classプロパティの設定値が表示された「Hibernateのプロパティの追加」ダイアログ・ボックス"]
エディタの「XML」タブをクリックすると、ファイルがXMLビューに表示されます。ファイルの内容は次のようになります(3つの新しいプロパティは太字)。
[source,xml]
----
<hibernate-configuration>
<session-factory name="session1">
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/sakila</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">######</property>
*<property name="hibernate.show_sql">true</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</property>*
</session-factory>
</hibernate-configuration>
----
. 変更内容をファイルに保存します。
このファイルは、再度編集する必要がないため閉じてかまいません。
== ``HibernateUtil.java`` ヘルパー・ファイルの作成
Hibernateを使用するには、起動を処理し、Hibernate ``SessionFactory`` にアクセスしてセッション・オブジェクトを取得するヘルパー・クラスを作成する必要があります。このクラスは、 ``configure()`` をコールし、 ``hibernate.cfg.xml`` 構成ファイルをロードし、次に ``SessionFactory`` をビルドしてセッション・オブジェクトを取得します。
この項では、新規ファイル・ウィザードを使用してヘルパー・クラスである ``HibernateUtil.java`` を作成します。
1. 「ソース・パッケージ」ノードを右クリックし、「新規」>「その他」を選択して新規ファイル・ウィザードを開きます。
2. 「カテゴリ」の一覧から「Hibernate」を選択し、「ファイル・タイプ」の一覧から「HibernateUtil.java」を選択します。「次」をクリックします。
3. クラス名に「*HibernateUtil*」、パッケージに「*dvdrental*」と入力します。「終了」をクリックします。
image::images/hibernate-util-wizard.png[title="HibernateUtilウィザードのスクリーンショット"]
「終了」をクリックすると、 ``HibernateUtil.java`` がエディタに表示されます。このファイルは、編集する必要がないため閉じてかまいません。
== Hibernateのマッピング・ファイルおよびJavaクラスの生成
このチュートリアルでは、POJO (プレーン・オールドJavaオブジェクト)を使用して、これから使用するデータベース内の各表内のデータを表します。Javaクラスが、表内の列のフィールドを指定し、データの取得と書込みに単純な取得メソッドおよび設定メソッドを使用します。POJOを表にマップするには、Hibernateマッピング・ファイルを使用するか、クラス内で注釈を使用します。
データベースからのHibernateのマッピング・ファイルとPOJOウィザードを使用して、データベース表に基づいて複数のPOJOとマッピング・ファイルを作成できます。ウィザードを使用し、目的のPOJOとマッピング・ファイルのためのすべての表を選択すると、IDEでデータベース表に基づいてファイルが生成され、 ``hibernate.cfg.xml`` にマッピング・エントリが追加されます。ウィザードを使用する場合、たとえばPOJOのみにするなど、IDEで生成するファイルを選択でき、また、たとえばEJB 3注釈を使用するコードの生成するなど、コード生成オプションを選択できます。
*注意:*IDEには、個別のPOJOとマッピング・ファイルを最初から作成するウィザードもあります。
=== Hibernateリバース・エンジニアリング・ファイルの作成
データベースからのHibernateのマッピング・ファイルとPOJOウィザードを使用する場合、最初に ``hibernate.reveng.xml`` リバース・エンジニアリング・ファイルを作成する必要があります。データベースからのHibernateのマッピング・ファイルとPOJOウィザードには、 ``hibernate.reveng.xml`` および ``hibernate.cfg.xml`` が必要です。
リバース・エンジニアリング・ファイルを使用すると、データベース・マッピング戦略をより詳細に制御できます。Hibernateリバース・エンジニアリング・ウィザードでは、XMLエディタで編集できるデフォルト構成を持つリバース・エンジニアリング・ファイルが作成されます。
Hibernateリバース・エンジニアリング・ファイルを作成するには、次の手順を実行します。
1. 「プロジェクト」ウィンドウで「ソース・パッケージ」ノードを右クリックし、「新規」>「その他」を選択して新規ファイル・ウィザードを開きます。
2. Hibernate」カテゴリで「Hibernateリバース・エンジニアリング・ウィザード」を選択します。「次」をクリックします。
3. ファイル名に ``hibernate.reveng`` を指定し、フォルダに ``src/java`` を指定します。「次」をクリックします。
4. 選択されていない場合、 ``hibernate.cfg.xml`` を「構成ファイル」ドロップダウン・リストから選択します。
5. 「使用可能な表」から次の表を選択し、「追加」をクリックして「選択した表」に追加します。
* actor
* category
* film
* film_actor
* film_category
* language
「終了」をクリックします。
image::images/hibernate-reveng-wizard.png[title="新規Hibernateリバース・エンジニアリング・ウィザード"]
このウィザードでは、 ``hibernate.reveng.xml`` リバース・エンジニアリング・ファイルが生成され、ファイルはエディタに表示されます。リバース・エンジニアリング・ファイルは、編集する必要がないため閉じてかまいません。
``hibernate.reveng.xml`` ファイルの操作の詳細は、link:http://docs.jboss.org/tools/2.1.0.Beta1/hibernatetools/html/reverseengineering.html[+第5章: リバース・エンジニアリングの制御+](link:http://docs.jboss.org/tools/2.1.0.Beta1/hibernatetools/html/[+Hibernate Toolsリファレンス・ガイド+])を参照してください。
=== Hibernateマッピング・ファイルとPOJOの作成
データベースからのHibernateのマッピング・ファイルとPOJOウィザードを使用して、ファイルを生成できます。このウィザードでは、ウィザードで選択した表ごとに、POJOおよび対応するマッピング・ファイルを生成できます。マッピング・ファイルはXMLファイルで、表の列をPOJOのフィールドにマップする方法に関するデータが含まれています。ウィザードを使用するには、 ``hibernate.reveng.xml`` ファイルと ``hibernate.cfg.xml`` ファイルが必要です。
ウィザードを使用してPOJOとマッピング・ファイルを作成するには、次の手順を実行します。
1. 「プロジェクト」ウィンドウで「ソース・パッケージ」ノードを右クリックし、「新規」>「その他」を選択して新規ファイル・ウィザードを開きます。
2. 「データベースからのHibernateのマッピング・ファイルとPOJO」を「Hibernate」カテゴリから選択します。「次」をクリックします。
3. ドロップダウン・リストで、 ``hibernate.cfg.xml`` ファイルと ``hibernate.reveng.xml`` ファイルが選択されていることを確認します。
4. 「一般的な設定」で「*JDK 5言語機能*」を選択します。
5. 「*ドメイン・コード*」および「*Hibernate XMLのマッピング*」オプションが選択されていることを確認します。
6. パッケージ名に「*dvdrental*」を選択します。「終了」をクリックします。
image::images/hibernate-pojo-wizard2.png[title="「Hibernateのマッピング・ファイルとPOJOの生成」ウィザード"]
「終了」をクリックすると、POJOHibernateのマッピング・ファイルが生成され、 ``hibernate.reveng.xml`` で指定した列にフィールドがマップされます。また、 ``hibernate.cfg.xml`` にマッピング・エントリが追加されます。
[source,xml]
----
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/sakila</property>
<property name="hibernate.connection.username">myusername</property>
<property name="hibernate.connection.password">mypassword</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</property>
<mapping resource="dvdrental/FilmActor.hbm.xml"/>
<mapping resource="dvdrental/Language.hbm.xml"/>
<mapping resource="dvdrental/Film.hbm.xml"/>
<mapping resource="dvdrental/Category.hbm.xml"/>
<mapping resource="dvdrental/Actor.hbm.xml"/>
<mapping resource="dvdrental/FilmCategory.hbm.xml"/>
</session-factory>
</hibernate-configuration>
----
*注意:* ``hibernate.cfg.xml`` ファイルで、 ``mapping`` 要素が ``property`` 要素の後に表示されていることを確認してください。
``dvdrental`` パッケージを展開すると、ウィザードによって生成されたファイルを確認できます。
image::images/hib-projectswindow.png[title="生成されたPOJOを示す「プロジェクト」ウィンドウ"]
特定の表を特定のクラスにマップするHibernateマッピング・ファイルを作成する場合、Hibernateマッピング・ウィザードを使用できます。
``hibernate.reveng.xml`` ファイルの操作の詳細は、link:http://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html[+第5章: 基本的なO/Rマッピング+](link:http://docs.jboss.org/hibernate/stable/core/reference/en/html/[+Hibernate Reference Documentation+])を参照してください。
== ``FilmHelper.java`` ヘルパー・クラスの作成
データベースに対するHibernate問合せの実行に使用するヘルパー・クラスを ``dvdrental`` パッケージ内に作成します。Hibernate問合せ言語(HQL)エディタを使用して、データを取り出す問合せを構築し、テストします。問合せをテストしたら、問合せを構築および実行するメソッドをヘルパー・クラス内に作成します。次に、ヘルパー・クラス内のメソッドをJSF管理対象Beanから呼び出します。
=== クラスの作成
この項では、新規ファイル・ウィザードを使用して、ヘルパー・クラス ``FilmHelper.java`` ``dvdrental`` パッケージ内に作成します。 ``HibernateUtil.java`` 内の ``getSessionFactory`` をコールしてHibernateセッションを作成し、データベースからデータを取り出す問合せを作成するヘルパー・メソッドをいくつか作成します。ヘルパー・メソッドはJSPページから呼び出します。
1. ``dvdrental`` 」ソース・パッケージ・ノードを右クリックし、「新規」>「Javaクラス」を選択して、新規ファイル・ウィザードを開きます。
2. クラス名に「*FilmHelper*」と入力します。
3. 「パッケージ」として*dvdrental*が選択されていることを確認します。「終了」をクリックします。
4. 次のコード(太字部分)を追加して、Hibernateセッションを作成します。
[source,java]
----
public class FilmHelper {
*Session session = null;
public FilmHelper() {
this.session = HibernateUtil.getSessionFactory().getCurrentSession();
}*
}
----
. エディタ上で右クリックし、「インポートを修正」([Alt]-[Shift]-[I]、Macの場合は[⌘]-[Shift]-[I])を選択して必要なインポート文( ``org.hibernate.Session`` )を追加し、変更を保存します。
ここで ``FilmHelper.java`` を変更して、データベースに対して問合せを実行するメソッドを追加します。
=== HQL問合せを使用した映画タイトルの列挙と俳優の取得
この課題では、データベースを問合せしてFilm表から映画のタイトルのリストを取り出す、Hibernate問合せ言語(HQL)問合せ作成します。次に、特定の映画に含まれる俳優をフェッチするため、Actor表およびFilm_actor表の両方に問合せを実行するメソッドを追加します。
Film表には1000件のレコードがあるため、映画のリストを取得するメソッドは、 ``filmId`` 主キーに基づいてレコードを取得できる必要があります。HQL問合せの構成とテストには、HQLエディタを使用します。正しい問合せを作成した後、適切な問合せを生成できるクラスにメソッドを追加します。
1. 「プロジェクト」ウィンドウでプロジェクトのノードを右クリックし、「消去してビルド」を選択します。
2. 「プロジェクト」ウィンドウで「 ``hibernate.cfg.xml`` 」を右クリックし、「HQL問合せの実行」を選択して、HQL問合せエディタを開きます。
3. ツールバーのドロップダウン・リストから「hibernate.cfg」を選択します。
4. 接続をテストするには、エディタで次のように入力し、ツールバーの「HQL問合せの実行」ボタン(image:images/run_hql_query_16.png[title="「HQL問合せの実行」ボタン"])をクリックします。
[source,java]
----
from Film
----
HQL問合せの実行」をクリックすると、HQL問合せエディタの下部ウィンドウで問合せの結果を確認できます。
image::images/hibernate-hqleditor1.png[title="「Hibernateのマッピング・ファイルとPOJOの生成」ウィザード"]
SQL」ボタンをクリックすると、対応するSQL問合せを確認できます。
[source,java]
----
select film0_.film_id as col_0_0_ from sakila.film film0_
----
. 次の問合せを入力して、filmId100から200の間に含まれるレコードをFilm表から取り出します。
[source,java]
----
from Film as film where film.filmId between 100 and 200
----
結果ウィンドウにレコードのリストが表示されます。問合せが適切な結果を返すことをテストできたので、この問合せをヘルパー・クラスで使用できます。
. ``FilmHelper.java`` に次のメソッド ``getFilmTitles`` を追加して、filmIdが、変数 ``startID`` ``endID`` で指定する範囲内にある映画を取り出します。
[source,java]
----
public List getFilmTitles(int startID, int endID) {
List<Film> filmList = null;
try {
org.hibernate.Transaction tx = session.beginTransaction();
Query q = session.createQuery ("from Film as film where film.filmId between '"+startID+"' and '"+endID+"'");
filmList = (List<Film>) q.list();
} catch (Exception e) {
e.printStackTrace();
}
return filmList;
}
----
. 特定の映画から俳優を取得する次のメソッド ``getActorsByID`` を追加します。メソッドは、入力変数として ``filmId`` を使用し、問合せを構成します。
[source,java]
----
public List getActorsByID(int filmId){
List<Actor> actorList = null;
try {
org.hibernate.Transaction tx = session.beginTransaction();
Query q = session.createQuery ("from Actor as actor where actor.actorId in (select filmActor.actor.actorId from FilmActor as filmActor where filmActor.film.filmId='" + filmId + "')");
actorList = (List<Actor>) q.list();
} catch (Exception e) {
e.printStackTrace();
}
return actorList;
}
----
. インポートを修正して変更内容を保存します。
インポートを修正するときは、 ``java.util.List`` ``org.hibernate.Query`` を選択します。
=== ヘルパー・メソッドの追加
ここでは、入力変数に基づいて問合せを作成するヘルパー・メソッドを追加します。問合せはHQL問合せエディタで確認できます。
1. ``filmId`` に基づいてカテゴリのリストを取り出す次のメソッドを追加します。
[source,java]
----
public Category getCategoryByID(int filmId){
List<Category> categoryList = null;
try {
org.hibernate.Transaction tx = session.beginTransaction();
Query q = session.createQuery("from Category as category where category.categoryId in (select filmCat.category.categoryId from FilmCategory as filmCat where filmCat.film.filmId='" + filmId + "')");
categoryList = (List<Category>) q.list();
} catch (Exception e) {
e.printStackTrace();
}
return categoryList.get(0);
}
----
. ``filmId`` に基づいて1つの映画を取り出す次のメソッドを追加します。
[source,java]
----
public Film getFilmByID(int filmId){
Film film = null;
try {
org.hibernate.Transaction tx = session.beginTransaction();
Query q = session.createQuery("from Film as film where film.filmId=" + filmId);
film = (Film) q.uniqueResult();
} catch (Exception e) {
e.printStackTrace();
}
return film;
}
----
. ``langId`` に基づいて映画の言語を取り出す次のメソッドを追加します。
[source,java]
----
public String getLangByID(int langId){
Language language = null;
try {
org.hibernate.Transaction tx = session.beginTransaction();
Query q = session.createQuery("from Language as lang where lang.languageId=" + langId);
language = (Language) q.uniqueResult();
} catch (Exception e) {
e.printStackTrace();
}
return language.getName();
}
----
. 変更を保存します。
== JSF管理対象Beanの作成
この課題では、JSF管理対象Beanを作成します。管理対象Beanのメソッドは、JSFページにデータを表示したり、ヘルパー・クラスのメソッドにアクセスしてレコードを取り出すために使用されます。JSF 2.0仕様によって、スコープを指定したりBeanに名前を指定するためのJSF管理対象Beanとしてクラスを識別するため、Beanクラスに注釈を使用できます。
管理対象Beanを作成するには、次の手順を実行します。
1. ``dvdrental`` ソース・パッケージ・ノードを右クリックして「新規」>「その他」を選択します。
2. JavaServer Faces」カテゴリからJSF管理対象Beanを選択します。「次」をクリックします。
3. 「クラス名」に「*FilmController*」と入力します。
Beanでメソッドをコールするときに、管理対象Bean ``filmController`` を、JSFページ ``index.xhtml`` ``inputText`` および ``commandButton`` の値として使用します。
. パッケージに「*dvdrental*」を選択します。
. 管理対象Beanに使用する名前に「*filmController*」と入力します。
. スコープを「セッション」に設定します。「終了」をクリックします。
image::images/hib-newmanagedbean.png[title="新規JSF管理対象Beanウィザード"]
「終了」をクリックすると、IDEBeanクラスを作成し、そのクラスがエディタに表示されます。IDEによって、 ``@ManagedBean`` 注釈と ``@SessionScoped`` 注釈が追加されています。
[source,java]
----
@ManagedBean
@SessionScoped
public class FilmController {
/** Creates a new instance of FilmController */
public FilmController() {
}
}
----
*注意:*管理対象Beanの名前は明示的に指定されていません。デフォルトでは、Beanの名前はクラス名と同じになり、小文字で始まります。Beanの名前をクラス名とは異なるものにするには、 ``@ManagedBean`` 注釈のパラメータとして明示的に名前を指定します(たとえば、 ``@ManagedBean(name="myBeanName")`` )。
1. このクラスに、次のフィールド(太字部分)を追加します。
[source,java]
----
@ManagedBean
@SessionScoped
public class FilmController {
*int startId;
int endId;
DataModel filmTitles;
FilmHelper helper;
private int recordCount = 1000;
private int pageSize = 10;
private Film current;
private int selectedItemIndex;*
}
----
. 次の太字部分のコードを追加してFilmControllerインスタンスを作成し、映画を取り出します。
[source,java]
----
/** Creates a new instance of FilmController */
public FilmController() {
*helper = new FilmHelper();
startId = 1;
endId = 10;
}
public FilmController(int startId, int endId) {
helper = new FilmHelper();
this.startId = startId;
this.endId = endId;
}
public Film getSelected() {
if (current == null) {
current = new Film();
selectedItemIndex = -1;
}
return current;
}
public DataModel getFilmTitles() {
if (filmTitles == null) {
filmTitles = new ListDataModel(helper.getFilmTitles(startId, endId));
}
return filmTitles;
}
void recreateModel() {
filmTitles = null;
}*
----
. 表の表示とページへのナビゲートに使用される、次のメソッドを追加します。* public boolean isHasNextPage() {
if (endId + pageSize <= recordCount) {
return true;
}
return false;
}
public boolean isHasPreviousPage() {
if (startId-pageSize > 0) {
return true;
}
return false;
}
public String next() {
startId = endId+1;
endId = endId + pageSize;
recreateModel();
return "index";
}
public String previous() {
startId = startId - pageSize;
endId = endId - pageSize;
recreateModel();
return "index";
}
public int getPageSize() {
return pageSize;
}
public String prepareView(){
current = (Film) getFilmTitles().getRowData();
return "browse";
}
public String prepareList(){
recreateModel();
return "index";
}
*
index」または「browse」を返すメソッドによって、JSFナビゲーション・ハンドラは ``index.xhtml`` または ``browse.xhtml`` という名前のページを開くように求められます。JSF 2.0仕様では、Faceletsテクノロジを使用するアプリケーションで暗黙ナビゲーション・ルールを使用できます。このアプリケーションは、 ``faces-config.xml`` にナビゲーション・ルールが構成されていません。かわりに、ナビゲーション・ハンドラが、アプリケーション内で適切なページを検索しようとします。
. 追加の映画の詳細を取り出すヘルパー・クラスにアクセスする、次のメソッドを追加します。* public String getLanguage() {
int langID = current.getLanguageByLanguageId().getLanguageId().intValue();
String language = helper.getLangByID(langID);
return language;
}
public String getActors() {
List actors = helper.getActorsByID(current.getFilmId());
StringBuffer totalCast = new StringBuffer();
for (int i = 0; i < actors.size(); i++) {
Actor actor = (Actor) actors.get(i);
totalCast.append(actor.getFirstName());
totalCast.append(" ");
totalCast.append(actor.getLastName());
totalCast.append(" ");
}
return totalCast.toString();
}
public String getCategory() {
Category category = helper.getCategoryByID(current.getFilmId());
return category.getName();
}*
[source,java]
----
----
. インポートを修正([Ctrl]-[Shift]-[I])して変更内容を保存します。
エディタでコード補完を使用すると、コードの入力に役立ちます。
== Webページの作成
この課題では、データを表示するWebページを2つ作成します。IDEが生成した ``index.xhtml`` を変更して、データベース内の映画を表示する表を追加します。次に、表の「View」リンクをクリックしたときに映画の詳細を表示する ``browse.xhtml`` を作成します。また、 ``index.xhtml`` ``browse.xhtml`` で使用するJSFテンプレート・ページも作成します。
JSF 2.0およびFaceletsテンプレートの使用については、link:jsf20-intro.html[+JavaServer Faces 2.0入門+]を参照してください。
=== ``template.xhtml`` の作成
最初に、 ``index.xhtml`` ページと ``browse.xhtml`` ページの構成に使用する、JSF Faceletsテンプレート ``template.xhtml`` を作成します。
1. 「プロジェクト」ウィンドウで「DVDStore」プロジェクト・ノードを右クリックし、「新規」>「その他」を選択します。
2. JavaServer Faces」カテゴリで「Faceletsテンプレート」を選択します。「次」をクリックします。
3. 「ファイル名」に「*template*」と入力し、1つ目のCSSレイアウト・スタイルを選択します。
4. 「終了」をクリックします。
「終了」をクリックすると、エディタで ``template.xhtml`` ファイルが開きます。テンプレートには次のデフォルト・コードが含まれています。
[source,html]
----
<h:body>
<div id="top" class="top">
<ui:insert name="top">Top</ui:insert>
</div>
<div id="content" class="center_content">
<ui:insert name="content">Content</ui:insert>
</div>
</h:body>
----
. ``<ui:insert>`` 要素を変更して、デフォルトで生成される名前を「body」に変えます。
[source,html]
----
<div id="content" class="center_content">
<ui:insert name="*body*">Content</ui:insert>
</div>
----
. 変更を保存します。
``index.xhtml`` および ``browse.xhtml`` ``<ui:define name="body">`` 要素内の内容は、テンプレートの ``<ui:insert name="body">Content</ui:insert>`` で指定された場所に挿入されます。
=== ``index.xhtml`` の変更
Webアプリケーションを作成すると、IDEが自動的にページの ``index.xhtml`` を生成します。この課題では、ページを変更して映画のタイトルのリストを表示するようにします。JSFページはJSF管理対象BeanFilmControllerのメソッドをコールし、映画のリストを取り出して、映画のタイトルと説明の表を表示します。
1. 「プロジェクト」ウィンドウで「Webページ」フォルダを展開し、 ``index.xhtml`` をエディタで開きます。
新規プロジェクト・ウィザードで、次に示すデフォルトの ``index.xhtml`` を生成します。
[source,xml]
----
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
Hello from Facelets
</h:body>
</html>
----
. ページを変更し、JSF ``<ui:composition>`` 要素および ``<ui:define>`` 要素を使用するようにして、 ``<h:form>`` 要素を追加します。
[source,xml]
----
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
*xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:composition template="./template.xhtml">
<ui:define name="body">
<h:form>
</h:form>
</ui:define>
</ui:composition>*
</html>
----
タグの入力を開始すると、IDE ``xmlns:ui="http://java.sun.com/jsf/facelets"`` タグ・ライブラリ宣言を追加します。
``<ui:composition>`` 要素と ``<ui:define>`` 要素は、作成するページ・テンプレートと組み合せて使用されます。 ``<ui:composition>`` 要素は、このページによって使用されるテンプレートの場所を参照します。 ``<ui:define>`` 要素は、含まれているコードが占有するテンプレート内での位置を参照します。
. JSF管理対象Bean ``previous`` メソッドおよび ``next`` メソッドをコールする、次のナビゲーション・リンクを追加します。
[source,xml]
----
<ui:define name="body">
<h:form>
*<h:commandLink action="#{filmController.previous}" value="Previous #{filmController.pageSize}" rendered="#{filmController.hasPreviousPage}"/> 
<h:commandLink action="#{filmController.next}" value="Next #{filmController.pageSize}" rendered="#{filmController.hasNextPage}"/> *
</h:form>
</ui:define>
----
. 取り出された項目を表示する表を生成する次の ``dataTable`` 要素(太字部分)を追加します。
[source,xml]
----
<h:form styleClass="jsfcrud_list_form">
<h:commandLink action="#{filmController.previous}" value="Previous #{filmController.pageSize}" rendered="#{filmController.hasPreviousPage}"/> 
<h:commandLink action="#{filmController.next}" value="Next #{filmController.pageSize}" rendered="#{filmController.hasNextPage}"/> 
*<h:dataTable value="#{filmController.filmTitles}" var="item" border="0" cellpadding="2" cellspacing="0" rowClasses="jsfcrud_odd_row,jsfcrud_even_row" rules="all" style="border:solid 1px">
<h:column>
<f:facet name="header">
<h:outputText value="Title"/>
</f:facet>
<h:outputText value="#{item.title}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Description"/>
</f:facet>
<h:outputText value="#{item.description}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value=" "/>
</f:facet>
<h:commandLink action="#{filmController.prepareView}" value="View"/>
</h:column>
</h:dataTable>
<br/>*
</h:form>
----
. 変更を保存します。
これで、indexページにデータベース内の映画のタイトル・リストが表示されます。表の各行に、管理対象Bean ``prepareView`` メソッドを呼び出す「View」リンクがあります。 ``prepareView`` メソッドは「browse」を返し、 ``browse.xhtml`` を開きます。
*注意:* ``<f:facet>`` タグを入力すると、IDE ``xmlns:f="http://java.sun.com/jsf/core`` タグ・ライブラリ宣言を追加します。*ファイルにタグ・ライブラリが宣言されていることを確認してください。*
=== ``browse.xhtml`` の作成
ここでは、選択した映画の詳細を表示する ``browse.xhtml`` ページを作成します。Faceletsテンプレート・クライアント・ウィザードを使用すると、作成したJSF Faceletsテンプレート ``template.xhtml`` に基づいて、ページを作成できます。
1. 「プロジェクト」ウィンドウで「DVDStore」プロジェクト・ノードを右クリックし、「新規」>「その他」を選択します。
2. 「JavaServer Faces」カテゴリで「Faceletsテンプレート・クライアント」を選択します。「次」をクリックします。
image::images/hib-faceletsclient.png[title="新規ファイル・ウィザードの「Faceletsテンプレート・クライアント」ファイル・タイプ"]
. 「ファイル名」に「*browse*」と入力します。
. 「参照」をクリックして「ファイルを参照」ダイアログ・ボックスを開き、ページのテンプレートを特定します。
. 「Webページ」フォルダを展開し、「 ``template.xhtml`` 」を選択します。「ファイルを選択」をクリックします。
image::images/hib-browsetemplate.png[title="「ファイルを参照」ダイアログでのテンプレートの選択"]
. 「生成されたルート・タグ」に*<ui:composition>*を選択します。「終了」をクリックします。
「終了」をクリックすると、 ``browse.xhtml`` ファイルがエディタで開き、次のコードが表示されます。
[source,xml]
----
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
template="./template.xhtml">
<ui:define name="top">
top
</ui:define>
<ui:define name="body">
body
</ui:define>
</ui:composition>
----
新しいファイルが ``template.xhtml`` ファイルを指定し、 ``<ui:define>`` タグに ``name="body"`` プロパティがあることを確認できます。
. ``<ui:define>`` タグの間に次の太字のコードを追加してフォームを作成し、管理対象BeanFilmControllerでメソッドをコールして、データを取り出し、フォームを生成します。
[source,xml]
----
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
template="./template.xhtml"
*xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"*>
<ui:define name="top">
top
</ui:define>
<ui:define name="body">
*
<h:form>
<h:panelGrid columns="2">
<h:outputText value="Title:"/>
<h:outputText value="#{filmController.selected.title}" title="Title"/>
<h:outputText value="Description"/>
<h:outputText value="#{filmController.selected.description}" title="Description"/>
<h:outputText value="Genre"/>
<h:outputText value="#{filmController.category}"/>
<h:outputText value="Cast"/>
<h:outputText value="#{filmController.actors}"/>
<h:outputText value="Film Length"/>
<h:outputText value="#{filmController.selected.length} min" title="Film Length"/>
<h:outputText value="Language"/>
<h:outputText value="#{filmController.language}" title="Film Length"/>
<h:outputText value="Release Year"/>
<h:outputText value="#{filmController.selected.releaseYear}" title="Release Year">
<f:convertDateTime pattern="MM/dd/yyyy" />
</h:outputText>
<h:outputText value="Rental Duration"/>
<h:outputText value="#{filmController.selected.rentalDuration}" title="Rental DUration"/>
<h:outputText value="Rental Rate"/>
<h:outputText value="#{filmController.selected.rentalRate}" title="Rental Rate"/>
<h:outputText value="Replacement Cost"/>
<h:outputText value="#{filmController.selected.replacementCost}" title="Replacement Cost"/>
<h:outputText value="Rating"/>
<h:outputText value="#{filmController.selected.rating}" title="Rating"/>
<h:outputText value="Special Features"/>
<h:outputText value="#{filmController.selected.specialFeatures}" title="Special Features"/>
<h:outputText value="Last Update"/>
<h:outputText value="#{filmController.selected.lastUpdate}" title="Last Update">
<f:convertDateTime pattern="MM/dd/yyyy HH:mm:ss" />
</h:outputText>
</h:panelGrid>
<br/>
<br/>
<h:commandLink action="#{filmController.prepareList}" value="View All List"/>
<br/>
</h:form>
*
</ui:define>
</ui:composition>
</html>
----
``browse.xhtml`` ``index.xhtml`` が同じページ・テンプレートを使用していることが確認できます。
. 変更を保存します。
== プロジェクトの実行
アプリケーションの基本はこれで完了です。ここでアプリケーションを実行し、すべてが正常に動作するかを確認します。
1. メイン・ツールバーの「メイン・プロジェクトの実行」をクリックするか、「プロジェクト」ウィンドウでDVDStoreアプリケーション・ノードを右クリックして「実行」を選択します。
変更したファイルがすべて保存され、アプリケーションがビルドされて、サーバーにデプロイされます。IDEは、映画のリストを表示するURL ``http://localhost:8080/DVDStore/`` で、ブラウザ・ウィンドウを開きます。
image::images/hib-browser1.png[title="indexページに映画のリストが表示されたスクリーンショット"]
. ブラウザで、「View」をクリックして ``browse.xhtml`` をロードし、映画の詳細を表示します。
=== ソリューション・プロジェクトのダウンロード
次の方法で、このチュートリアルにソリューションをプロジェクトとしてダウンロードできます。
* link:https://netbeans.org/projects/samples/downloads/download/Samples/JavaEE/DVDStoreEE6.zip[+終了したプロジェクトのZIPアーカイブ+]をダウンロードします。
* 次の手順を実行して、プロジェクト・ソースをNetBeansのサンプルからチェックアウトします。
1. メイン・メニューから「チーム」>「Subversion」>「チェックアウト」を選択します。
2. 「チェックアウト」ダイアログ・ボックスで次のリポジトリURLを入力します。
``https://svn.netbeans.org/svn/samples~samples-source-code``
「次」をクリックします。
. 「参照」をクリックして「リポジトリ・フォルダを参照」ダイアログ・ボックスを開きます。
. ルート・ノードを展開し、*samples/javaee/DVDStoreEE6*を選択します。「OK」をクリックします。
. ソースのローカル・フォルダを指定します。
. 「終了」をクリックします。
「終了」をクリックすると、IDEではローカル・フォルダがSubversionリポジトリとして初期化され、プロジェクト・ソースがチェックアウトされます。
. チェックアウトが完了するときに表示されるダイアログで、「プロジェクトを開く」をクリックします。
*注意:*Subversionのインストールの詳細は、link:../ide/subversion.html[+NetBeans IDEでのSubversionガイド+]のlink:../ide/subversion.html#settingUp[+Subversionの設定+]の項を参照してください。
=== トラブルシューティング
チュートリアルのアプリケーションで発生する問題の多くは、GlassFish Server Open Source EditionMySQLデータベース・サーバーとの間の接続に原因があります。アプリケーションが正しく表示されない場合、またはサーバー・エラーが表示される場合、link:mysql-webapp.html[+MySQLデータベースを使用した単純なWebアプリケーションの作成+]のチュートリアルのlink:mysql-webapp.html#troubleshoot[+トラブルシューティング+]またはlink:../ide/mysql.html[+MySQLデータベースへの接続+]のチュートリアルを参照してください。
MySQLデータベースを使用するアプリケーションを初めてデプロイした場合、ソリューション・プロジェクトをダウンロードして実行すると、「出力」ウィンドウに次のエラーが表示される場合があります。
[source,java]
----
SEVERE: JDBC Driver class not found: com.mysql.jdbc.Driver
java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
at org.glassfish.web.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1509)
[...]
at java.lang.Thread.run(Thread.java:680)
SEVERE: Initial SessionFactory creation failed.org.hibernate.HibernateException: JDBC Driver class not found: com.mysql.jdbc.Driver
INFO: cleaning up connection pool: null
INFO: Domain Pinged: stable.glassfish.org
----
ブラウザ・ウィンドウに ``java.lang.ExceptionInInitializerError`` および次のスタック・トレースが表示される場合があります。
[source,java]
----
java.lang.ExceptionInInitializerError
at dvdrental.HibernateUtil.<clinit>(HibernateUtil.java:28)
...
Caused by: org.hibernate.HibernateException: JDBC Driver class not found: com.mysql.jdbc.Driver
...
Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
...
----
出力メッセージには、MySQLデータベースのJDBCドライバが見つからなかったことが示されます。最も可能性の高い原因は、MySQL JDBCドライバ・ファイルをGlassFishサーバー・インストールに追加する必要があるということです。ドライバがないことを確認し、ローカル・システムの ``_GLASSFISH-INSTALL_/glassfish/domains/domain1/lib`` ディレクトリに移動します(ここで、_GLASSFISH-INSTALL_GlassFishのインストール・ディレクトリです)。 ``domain1/lib`` ディレクトリにJDBCドライバ・ファイル(たとえば、`mysql-connector-java-5.1.13-bin.jar`など)が含まれていない場合、JDBCドライバをディレクトリにコピーする必要があります。サーバーのインストール時、MySQL JDBCドライバはGlassFishインストールに追加されません。
次の手順を実行して、GlassFishインストールに、MySQL JDBCドライバのコピーを追加できます。
1. link:http://dev.mysql.com/downloads/connector/j/[+MySQL Connector/J JDBCドライバ+]をダウンロードします。
2. ドライバを抽出し、GlassFishインストールの ``domain1/lib`` ディレクトリに、ドライバのファイル(たとえば、`mysql-connector-java-5.1.13-bin.jar`)をコピーします。
または、IDEを使用してMySQLデータベースを使用するアプリケーションを作成する場合、プロジェクトをデプロイすると、必要に応じてバンドルされているMySQL JDBCドライバがGlassFishサーバーに自動的にコピーされます。必要なJDBCドライバがIDEによってコピーされることを確認するには、メイン・メニューから「ツール」>「サーバー」を選択し、サーバー・マネージャを開いて、GlassFishサーバーに対して「JDBCドライバのデプロイメントを有効化」オプションが選択されていることを確認します。
MySQLデータベースを使用するWebアプリケーションを作成してデプロイした後、ローカルのGlassFishインストールの`domain1/lib`ディレクトリに移動すると、ディレクトリにJDBCドライバ・ファイルが含まれていることが確認できます。
link:/about/contact_form.html?to=3&subject=Feedback:%20Using%20Hibernate%20in%20a%20Web%20Application[+このチュートリアルに関するご意見をお寄せください+]
== 関連項目
* link:jsf20-support.html[+NetBeans IDEでのJSF 2.xのサポート+]
* link:jsf20-intro.html[+JavaServer Faces 2.x入門+]
* link:../../trails/java-ee.html[+Java EEおよびJava Webの学習+]