データバウンドコンポーネント
このチュートリアルでは、NetBeans IDE を使って、IDE に付属するデータベースからマスターデータと詳細データを表示する Web アプリケーションを作成し、配備します。このアプリケーションでは、JSF 1.2 (Woodstock) のドロップダウンリストから名前を選択すると、その人の旅行の記録をすべて示す表が表示されます。
このチュートリアルを使用する前に、IDE の基本部分を十分に理解し、「NetBeans Visual Web JSF 開発について」を読んで NetBeans IDE 開発環境の概要を参照してください。
目次
このチュートリアルに従うには、次のソフトウェアとリソースが必要です。
| NetBeans IDE |
Web および Java EE の version 6.1 または 6.0 |
| Java Developer Kit (JDK) |
version 6 または
version 5 |
JavaServer Faces コンポーネント /
Java EE プラットフォーム |
1.2 と Java EE 5* または
1.1 と J2EE 1.4
|
| GlassFish アプリケーションサーバー |
V2 |
| Travel データベース |
必須 |
* NetBeans IDE の Java EE 5 機能を活用するためには、GlassFish アプリケーションサーバー V2 UR2 などの、Java EE 5 仕様に完全に準拠したアプリケーションサーバーを使用してください。別のサーバーを使用している場合は、「リリースノート」と「FAQ」で既知の問題やその回避策を確認してください。サポートされているサーバーと Java EE プラットフォームについては、「リリースノート」を参照してください。
NetBeans IDE 6.1 を使用している方へ
- NetBeans 6.1 でプロジェクトを作成すると新しいオプションが含まれますが、これらのオプションはデフォルトのままでかまいません。たとえば、「ライブラリの格納用に専用フォルダを使用」チェックボックスは選択しないままにします。
- NetBeans IDE 6.1 には、要求時バインド機能があります。コンポーネントに Java コーディングが必要な場合は、Visual Web JSF アプリケーション内のコンポーネントにバインド属性を手動で追加する必要があります。バインド属性を追加するには、各コンポーネントを右クリックし、「バインド属性を追加」を選択します。詳細は、「On-demand Binding Attribute Wiki」を参照してください。
「ドロップダウンリスト」コンポーネントを含むページの作成
このチュートリアルでは、次の図の配備されたアプリケーションに示されるように、旅行センターのアプリケーションを作成します。
まず、新しくプロジェクトで作成した default Page 1.jsp に、「表」コンポーネントと「ドロップダウンリスト」コンポーネントを追加します。
注: NetBeans IDE 6.1 には要求時バインド機能があります。コンポーネントに Java コーディングが必要な場合は、Visual Web JSF アプリケーション内のコンポーネントにバインド属性を手動で追加する必要があります。バインド属性を追加するには、各コンポーネントを右クリックし、「バインド属性を追加」を選択します。詳細は、「On-demand Binding Attribute Wiki」を参照してください。
-
GlassFish V2 Application Server と Visual Web JavaServer Faces フレームワークを使用する、新しい Web アプリケーションプロジェクトを「DataboundComponents」という名前で作成します。
「Page1」という最初のページが作成され、そのページがビジュアルデザイナに表示されます。
注: NetBeans 6.1 でプロジェクトを作成すると新しいオプションが含まれますが、これらのオプションはデフォルトのままでかまいません。たとえば、「ライブラリの格納用に専用フォルダを使用」チェックボックスは選択しないままにします。
- 「パレット」ウィンドウの「Woodstock 基本」ノードを展開し、「ラベル」コンポーネントをページの左側にドラッグします。「
Select Name:」と入力して Enter キーを押します。
- 「ラベル」コンポーネントの右側に「ドロップダウンリスト」コンポーネントをドラッグします。
- 「ドロップダウンリスト」コンポーネントの「プロパティー」ウィンドウで「id」プロパティーを
personIdDD に変更します。
Ctrl-Shift キーを押しながら、「ドロップダウンリスト」コンポーネントを「ラベル」コンポーネントまでドラッグし、2 つのコンポーネントを関連付けます。
「ラベル」コンポーネントの「for」プロパティーが personIdDD に設定されます。
「パレット」ウィンドウから「メッセージグループ」コンポーネントをページ上の右上隅などの端の方にドラッグします。
このコンポーネントは、プログラミングのエラーを診断するのに便利です。info(String)、error(String)、warn(String)、または fatal(String) メソッドを呼び出すことで、このコンポーネントに診断メッセージを表示できます。「メッセージグループ」コンポーネントには、String 型の引数の値が表示されます。また、このコンポーネントには、デフォルトで実行時エラー、妥当性検査エラー、および変換エラーに関するメッセージが表示されます。
コンポーネントのデータベースへの接続
IDE 作業スペースの左側に表示される「サービス」ウィンドウには、「データベース」ノードが含まれます。「データベース」ノードには、IDE に追加されたすべてのデータベースドライバと接続が表示されます。
NetBeans IDE にはサンプルの Travel データベースが付属しており、これは「データベース」ノードの下に表示されます。
データベースをコンポーネントにバインドすると、コンポーネントとデータベース表の間に行セットの層とデータプロバイダの層の、2 つの層が作成されます。行セットの層でデータベースに接続し、クエリーが実行され、結果セットが管理されます。データプロバイダの層は、行セット、配列オブジェクト、エンタープライズ JavaBeans オブジェクトなどのさまざまなデータにアクセスするための共通のインタフェースを提供します。
一般に、行セットオブジェクトを操作するのは、クエリーのパラメータを設定するときだけです。その他のほとんどの場合は、データプロバイダを使ってデータのアクセスや操作を行います。データプロバイダの API を使用すると、ラップするデータの種類 (使用するデータプロバイダの実装) に関係なく同じ API を使用できるため、学習曲線を短くできます。
チュートリアルのこの節では、Travel データベースの PERSON 表を使用して、「ドロップダウンリスト」コンポーネントの選択項目を指定します。
-
「サービス」ウィンドウで、「データベース」ノードを展開し、TRAVEL データベースが接続されているかどうかを確認します。
Travel データベースのバッジの jdbc ノードが壊れていてノードを展開できない場合、IDE は、このデータベースに接続されていません。Travel データベースに接続するには、Travel の jdbc ノードを右クリックし、ポップアップメニューから「接続」を選択します。「接続」ダイアログが表示された場合は、「ユーザー」と「パスワード」に「travel」と入力し、「セッション中はパスワードを保存」を選択して、「了解」をクリックします。Travel データベースの jdbc ノードが表示されない場合は、FAQ「How do I enable the sample Travel database for MySQL in NetBeans IDE」で、データベースを IDE で使用できるようにする情報を参照してください。
-
「Travel」>「表」ノードを展開します。
「表」の下には、CARRENTAL や FLIGHT など、データベース内の各表のノードが表示されます。次の図に、「サービス」ウィンドウで展開した「表」ノードを示します。
-
「サービス」ウィンドウから「PERSON」をドラッグし、「ドロップダウンリスト」の上にドロップします。
「ドロップダウンリスト」コンポーネントに「abc」というテキストが表示されます。「abc」のテキストは、表示フィールドが String 型オブジェクトにバインドされていることを示します。この例では、SQL 型 varchar のデータベース列です。さらに、IDE によってデータベース表の不可視の personDataProvider コンポーネントが追加されます。personDataProvider コンポーネントは「ナビゲータ」ウィンドウに表示されます。また、SessionBean1 に personRowSet プロパティーが追加されます。
「ドロップダウンリスト」を右クリックし、ポップアップメニューから「データにバインド」を選択します。次の図に示すような「データにバインド」ダイアログが表示されます。
「ドロップダウンリスト」コンポーネントにデータをバインドするときは、リスト内で表示する項目 (表示フィールド) と、プログラムで使用する値 (値フィールド) を指定する必要があります。通常は、人の名前など、データベース表に含まれる意味のある値を表示し、プログラム内では ID など一意の識別子を使用します。ただし、このアプリケーションでは、このあとの 2 つの手順で説明するように、値フィールドと表示フィールドの両方を同一のデータベース列 (PERSON.NAME) にバインドします。
- 「データにバインド」ダイアログの「値フィールド」リストで、「PERSON.PERSONID」を選択して、コンポーネントの getSelected メソッドが選択項目の PERSON.PERSONID を返すようにします。
- 「表示フィールド」リストで「PERSON.NAME」を選択し、ドロップダウンリストにデータベースの PERSON.NAME 列の値が挿入されるようにします。
- 「閉じる」をクリックします。
-
メインツールバーで「実行」>「主プロジェクトを実行」をクリックします。
変更内容がすべて保存され、Web アプリケーションが構築、配備、および実行されます。まず、「出力」ウィンドウが IDE 下部に表示されます。このウィンドウには、コンパイルと配備の準備に関する情報が出力されます。構築中に問題が発生した場合は、まず「出力」ウィンドウを確認してください。次に、配備の状態を示すダイアログが開きます。配備が完了すると、アプリケーションを実行するための Web ブラウザが開きます。ブラウザでページが表示されるときに、PERSON 表の NAME 列のデータがドロップダウンリストに表示されます。
「表」コンポーネントの追加
次に、アプリケーションに「表」コンポーネントを追加し、コンポーネントをデータベース表に接続します。
注: NetBeans IDE 6.1 には要求時バインド機能があります。コンポーネントに Java コーディングが必要な場合は、Visual Web JSF アプリケーション内のコンポーネントにバインド属性を手動で追加する必要があります。バインド属性を追加するには、各コンポーネントを右クリックし、「バインド属性を追加」を選択します。詳細は、「On-demand Binding Attribute Wiki」を参照してください。
- パレットから「表」コンポーネントをドラッグし、「ドロップダウンリスト」コンポーネントの下に置きます。
- 「サービス」ウィンドウで、「Travel」>「表」ノードを展開します。
-
「サービス」ウィンドウから「TRIP」をドラッグし、「表」コンポーネントのタイトルバーの上へドロップします。
注: TRIP データベースを「表」コンポーネントの別の部分にドロップした場合は、「ターゲットを選択」ダイアログが表示されます。「ターゲットを選択」ダイアログで「table1」を選択し、「了解」をクリックしてください。
-
「表」コンポーネントを右クリックし、「表レイアウト」を選択します。
「表レイアウト」ダイアログの「選択」リストに表の列がすべて表示されます。「選択」リストの項目を使用して、「表」コンポーネントに表示する列を指定します。
- Ctrl キーを押したままクリックすることにより、「選択」リスト内の TRIP.DEPDATE、TRIP.DEPCITY、および TRIP.DESTCITY を除く項目を選択します。
「<」ボタンをクリックします。
次の図に示すように、選択した項目が「使用可能」リストへ移動し、次の 3 つの項目が「選択」リストに残ります。
「閉じる」をクリックします。
次の図に示すように、ビジュアルデザイナで「表」コンポーネントに 3 つの列が表示されます。
SQL クエリーの変更
ここでは、tripRowSet オブジェクトの SQL クエリーを変更し、クエリーによって TRIPTYPE 表のデータも返されるようにします。また、旅行の種類の説明を表示するように「表」コンポーネントを変更します。
「ナビゲータ」ウィンドウで「SessionBean1」ノードが展開されていない場合は、展開します。
「ナビゲータ」ウィンドウの「SessionBean1」セクションで、「tripRowSet」ノードを右クリックし、「SQL 文を編集」を選択します。
編集領域にクエリーエディタが表示され、「tripRowSet」タブが表示されます。
ヒント: 「出力」ウィンドウが開いている場合は、ウィンドウを閉じてクエリーエディタに使用できるスペースを広げます。
-
次の図に示すように、「サービス」ウィンドウから「Travel」>「表」>「TRIPTYPE」ノードをドラッグし、デザインビューにドロップします。
別の表の図が表示され、2 つの図がリンクされます。このリンクは結合を表します。「ソースコード」区画で select 文がどのように変更されているかを確認してください。
TRIPTYPE 表内の TRIPTYPEID のチェックボックスの選択を解除します。
この操作によって、次の図に示すように、結果セットと、「ソースコード」区画内の SQL クエリーからこれらの列が削除されます。
- SQL クエリーエディタを開いたままにします。
- 編集領域で「Page1」タブをクリックします。
ビジュアルデザイナで、「表」コンポーネントを右クリックし、「表レイアウト」を選択します。
「表レイアウト」ダイアログが表示されます。tripRowSet の SQL クエリーを変更したので、使用可能な列が増えています。
-
「選択」リストに TRIPTYPE.DESCRIPTION 列を追加して、「了解」をクリックします。
「表」コンポーネントに 4 つ目の列が表示されます。
表示される行の制御
TRIP 表のデータプロバイダを追加したときに、行セットオブジェクトと、表内のすべての列のすべての行を返す SQL クエリーが作成されました。この時点でアプリケーションを配備し、実行した場合、「表」コンポーネントには、TRIP 表のすべての旅行情報が表示されます。
このアプリケーションでは、「表」コンポーネントには、「ドロップダウンリスト」コンポーネントで名前を選択した人の旅行情報だけを表示します。表に表示される情報を制約するには、tripRowSet オブジェクトのクエリーを編集して、「ドロップダウンリスト」コンポーネントと「表」コンポーネントの間でマスターと詳細の関係を作成します。
- 編集領域で「jdbc:derby://localhost:1527/travel」タブをクリックして、クエリーエディタに切り替えます。
- クエリーエディタのデザイングリッドで、PERSONID 行の任意のセルを右クリックし、「クエリー条件を追加」を選択します。
- 「比較」ドロップダウンリストを「
=等しい」に設定し、「パラメータ」ラジオボタンを選択して「了解」をクリックします。
PERSONID の「条件」列に「=?」と表示され、SQL クエリーに次の WHERE 句が追加されます。
| コード例 1:SQL クエリー内の WHERE 句 |
WHERE TRAVEL.TRIP.PERSONID = ? |
トラブルシューティングのヒント: この時点で、クエリーが正しく設定されているかどうかを確認できます。クエリーエディタ内で右クリックし、「クエリーを実行」を選択します。「パラメータ値を指定」ダイアログで、パラメータ TRAVEL.TRIP.PERSONID の値に「1」を入力し、「了解」をクリックします。PERSONID が 1 のクエリーの出力は、クエリーエディタの結果の区画に入ります。
-
クエリーエディタのデザイングリッドで、DEPDATE 行の「ソート方法」セルをクリックし、ドロップダウンリストから「昇順にソート」を選択します。
ソートの順序が自動的に設定され、SQL クエリーにソート句が追加されます。
- クエリーエディタを閉じます。
ビジュアルデザイナで、「ドロップダウンリスト」コンポーネントをダブルクリックします。
Page1 クラスのソースが Java エディタに表示され、personIdDD_processValueChange メソッドの本体内にカーソルが配置されます。イベントハンドラメソッドのスタブは、「ドロップダウンリスト」コンポーネントをはじめてダブルクリックしたときに作成されます。
personIdDD_processValueChange メソッドの本体を次のコード (太字部分) に置き換えます。
| コード例 2:「ドロップダウンリスト」コンポーネントの値変更イベント処理 |
public void personIdDD_processValueChange(ValueChangeEvent event) {
try {
getSessionBean1().getTripRowSet().setObject(
1, personIdDD.getSelected());
tripDataProvider.refresh();
} catch (Exception e) {
error("Cannot switch to person " +
personDataProvider.getValue(
"PERSON.PERSONID"));
log("Cannot switch to person " +
personDataProvider.getValue(
"PERSON.PERSONID"), e);
}
}
|
このコードは、ドロップダウンリストで現在選択されている名前 (NAME) の PERSONID の値を、tripRowSet オブジェクトの SQL 文のパラメータにバインドし、クエリーを実行し、新しい結果セットを取得します。
setObject メソッドによって、クエリー内の ? が PERSONID の値に置き換わります。refresh メソッドによって新しいクエリーが実行され、結果セットが更新されます。メソッド呼び出しを右クリックし、ポップアップメニューから「Javadoc を表示」を選択すると、これらのメソッドについての説明を表示できます。データプロバイダまたは行セットの Javadoc を表示するには、それぞれ「ヘルプ」>「Javadoc 参照」>「Data Provider」または「ヘルプ」>「Javadoc 参照」>「RowSet」を選択します。
ユーザーの問題を検出および診断できるように、log メソッドによって、メッセージと関連付けられているスタックトレースがアプリケーションサーバーのログへ送信されます。サーバーのログを表示するには、「サービス」ウィンドウでサーバーノードを右クリックし、ポップアップメニューから「サーバーログを表示」を選択します。
- Alt-Shift-F キーを押して、コードを再フォーマットします。
- ソースコードの
prerender メソッドを検索します。
prerender メソッドの本体を次のコード (太字部分) に置き換えます。
| コード例 3: ページが最初に表示されるときにマスターデータと詳細データを同期 |
public void prerender() {
if ( personIdDD.getSelected() == null ) {
try {
personDataProvider.cursorFirst();
getSessionBean1().getTripRowSet().setObject(
1, personDataProvider.getValue("PERSON.PERSONID"));
tripDataProvider.refresh();
} catch (Exception e) {
error("Cannot switch to person " +
personDataProvider.getValue("PERSON.PERSONID"));
log("Cannot switch to person " +
personDataProvider.getValue("PERSON.PERSONID"), e);
}
}
} |
prerender メソッドのコードは、Web ブラウザにページが表示される前に呼び出されます。
- Alt-Shift-F キーを押して、コードを再フォーマットします。
- 編集用ツールバーの「デザイン」をクリックし、ビジュアルデザイナに戻ります。
「ドロップダウンリスト」コンポーネントを右クリックし、「変更時に自動送信」を選択します。
「プロパティー」ウィンドウで、「onchange」プロパティーに次のコードが表示されます。
| コード例 4:「onchange」プロパティーのコード |
webuijsf.suntheme.common.timeoutSubmitForm(this.form, 'personIdDD');
|
実行中の Web アプリケーションでユーザーがドロップダウンリストの選択内容を変更すると、ページが自動的に送信されます。
メインツールバーで「主プロジェクトを実行」をクリックします。
変更したファイルがすべて保存され、アプリケーションが再構築され、サーバーに再配備されます。
- 「ドロップダウンリスト」コンポーネントから名前を選択し、「表」コンポーネントでマスターデータと詳細データが同期される様子を確認します。DESTCITY 列のヘッダーをクリックし、「表」コンポーネントで行がソートされる様子を確認します。
その他の可能な操作
試してみましょう。 「静的テキスト」コンポーネントを「ドロップダウンリスト」コンポーネントの右側に追加します。「静的テキスト」コンポーネントを右クリックし、「データにバインド」を選択します。「データプロバイダ」ドロップダウンリストで personDataProvider を選択し、コンポーネントを PERSON.JOBTITLE にバインドします。プログラムを実行し、ドロップダウンリストから別の名前を選択します。役職が変更されないことに注目してください。これは、アプリケーションによって personDataProvider をドロップダウンリストから選択した項目と同期させる必要があるからです。次のコード (太字部分) を prerender メソッドに追加し、アプリケーションを再度実行します。役職が選択した名前によって変わります。
注: NetBeans IDE 6.1 には要求時バインド機能があります。コンポーネントに Java コーディングが必要な場合は、Visual Web JSF アプリケーション内のコンポーネントにバインド属性を手動で追加する必要があります。バインド属性を追加するには、各コンポーネントを右クリックし、「バインド属性を追加」を選択します。詳細は、「On-demand Binding Attribute Wiki」を参照してください。
| コード例 5: personDataProvider と選択した人の同期 |
public void prerender() {
if ( personIdDD.getSelected() == null ) {
try {
personDataProvider.cursorFirst();
getSessionBean1().getTripRowSet().setObject(
1, personDataProvider.getValue("PERSON.PERSONID"));
tripDataProvider.refresh();
} catch (Exception e) {
error("Cannot switch to person " +
personDataProvider.getValue("PERSON.PERSONID"));
log("Cannot switch to person " +
personDataProvider.getValue("PERSON.PERSONID"), e);
}
}
else {
try {
// Synchronize data provider with current selection
personDataProvider.setCursorRow(
personDataProvider.findFirst(
"PERSON.PERSONID", personIdDD.getSelected()));
} catch (Exception e) {
error("Cannot switch to person " +
personIdDD.getSelected());
log("Cannot switch to person " +
personIdDD.getSelected(), e);
}
}
}
|
試してみましょう。表のレイアウトオプションを操作します。「表」コンポーネントを右クリックし、ポップアップメニューから「表レイアウト」を選択します。「ヘッダーテキスト」を「出発日」、「出発地」、「到着地」、および「説明」に変更します。ダイアログの「オプション」タブで、表のタイトルを「旅行」に設定します。「ページ付けを有効」を選択し、「ページサイズ」を「3」に設定します。アプリケーションを実行し、変更内容が表の表示にどのように影響するかを確認します。
注: ページ付けのオプションを使用する場合は、personIdDD_processValueChange メソッドの tripDataProvider.refresh() 文のあとに tableRowGroup1.setFirst(0); を追加します。このコードによって、ドロップダウンリストから新しい名前が選択されたときに必ず最初のページが表示されます。
試してみましょう。「ドロップダウンリスト」コンポーネントと「表」コンポーネントを含む Web アプリケーションを構築します。「ドロップダウンリスト」コンポーネントに TRIPTYPE.DESCRIPTION を表示します。「表」コンポーネントに、選択されている TRIPTYPE と TRIPTYPEID が同じである TRIP レコードをすべて表示します。
試してみましょう。 prerender メソッドと personIdDD_processValueChange メソッドの重複するコードによって、詳細の行セットが 2 回更新されるのではないかと思われるかもしれません。そのようなことはありません。このことを確認するには、log(メソッド名) 文をコンストラクタ、prerender メソッド、および personIdDD_processValueChange に追加します。「サービス」ウィンドウで、「サーバー」ノードを右クリックし、「サーバーログを表示」を選択します。プログラムを実行し、新しい名前を選択します。「出力」ウィンドウ内のサーバーログで、メソッドが次の順序で呼び出されたことがわかります。
- コンストラクタ
- prerender
- コンストラクタ
- personIdDD_processValueChange
ブラウザで最初にページが要求されるとき、アプリケーションによって Page1 のインスタンスが作成され、prerender が呼び出されます。サーバーによって応答 (HTML ページ) が送信され、Page1 のインスタンスが破棄されます。アプリケーションでは、ページの送信時にのみ値変更イベントが生成されるので (この例では新しい名前が選択されたとき)、値変更イベントハンドラは呼び出されません。
ドロップダウンリストから新しい名前を選択すると、ブラウザによってページが送信されます。アプリケーションによって Page1 の新しいインスタンスが作成され、前のインスタンスの値が復元されます (要求で渡される)。これは送信であり、また名前が変更されたので、アプリケーションによって値変更イベントが生成されます。その結果、personIdDD_processValueChange が呼び出され、アプリケーションによって行セットが更新されます。
値変更イベントハンドラが呼び出されたあとで、アプリケーションによって prerender メソッドが呼び出されます。ドロップダウンリストで値が選択されているので、アプリケーションでは、prerender メソッドの if セクションが省略されます。
まとめ
コンポーネントをデータベース表にバインドする手順は、次のとおりです。
- データベース表のノードをコンポーネントにドロップするか、ポップアップメニューから「データにバインド」を選択し、ドロップダウンリストから既存のデータプロバイダを選択することで、コンポーネントをデータベース表にバインドします。
- 「データにバインド」ダイアログを使って、コンポーネントが表示するデータベースの列を設定します。リストタイプのコンポーネントの場合は、返す列を設定します。「表レイアウト」ダイアログを使用して、「表」コンポーネントに表示するデータベース表の列を設定することもできます。
- 行セットオブジェクトのクエリーを変更するには、「ナビゲータ」ウィンドウから、行セットオブジェクトに対してクエリーエディタを開きます。
- 行セットオブジェクトの
setObject メソッドを呼び出して、クエリーのパラメータの値を設定します。データプロバイダの refresh メソッドを呼び出して、クエリーを実行し、結果セットを更新します。
- コンポーネントの値の変更時にページを自動的に送信するには、「変更時に自動送信」メニュー項目を使用します。
次の手順で詳細コンポーネントとマスターコンポーネントの同期をとります。
- ページ Bean の
prerender メソッドに、詳細データの行セットオブジェクトの setObject メソッドを呼び出して、クエリーのパラメータをデフォルト値 (ドロップダウンリストの最初の名前) に設定するコードを追加します。次に、refresh メソッドを呼び出してクエリーを実行します。
- マスターコンポーネントを processValueChanged メソッドにバインドします。このメソッドで詳細データの行セットオブジェクトの
setObject メソッドを呼び出して、新しいクエリーのパラメータを設定します。次に、refresh メソッドを呼び出してクエリーを実行します。
関連項目
更新日: 2008 年 4 月 15 日