同一テーブルでプロパティ項目を変更して永続化
1.2. 可変プロパティ項目を利用した簡単な応用例(商品マスタ登録画面)
このようなプロパティ定義の柔軟性は、どのようなアプリケーションから利用できるのでしょうか。ここでは、商品マスター・データを登録するサンプル・プログラムで説明します。
(a)デスクトップPC登録画面 | (b)液晶ディスプレイ登録画面 | (c)プリンタ登録画面 |
図3: 商品マスター・データを登録するサンプル・プログラム(クリックで拡大) |
このサンプルでは、図3(a、b、c)のように、コンピュータ関連商品を商品マスターに登録しています。
初期画面表示では、図3(a)のデスクトップPC登録画面が表示されます。データ項目の入力後に「登録」ボタンをクリックすることで、App Engineデータ・ストアへの永続化が完了します。次に、画面上部のラジオ・ボタンから液晶ディスプレイとプリンタを選択すると、それぞれ図3(b)、図3(c)のような画面表示に変わります。製品番号から価格までの基本項目以外に、製品種別に対応したスペックを登録できるようになっています。
このように、コンピュータ関連商品のマスター・データでは、コンピュータ本体やディスプレイ、プリンタなど、その品目種類によって登録するスペック・データが違ってきます。もし、このような登録内容のケースでRDBを使う場合、以下のような処理になります。
- 品目種別ごとにテーブルを分けてしまう
- 取扱品目に対するスペック項目を列項目としてすべて含むような大きなテーブルを作成し、必要な列項目だけを埋めていく
しかし、どちらの方式を採用したにせよ、処理内容が煩雑になることは避けられません。
これに対して、App Engineのデータ・ストアを使用する場合は、前述したようにプロパティ項目の指定はエンティティごとに任意なので、同じテーブルを使いながらすべての品目データを無駄なく登録することができるわけです。
このプログラムでは、3種類のコンピュータ商品を登録していますが、それぞれ登録する内容(プロパティ項目)は、図4の①、②、③のようになっています。エンティティは、コンピュータ商品としての基本項目(赤字)と、それぞれの商品種別に対応した個別のスペック項目から構成されています。スペック項目は、これ以外の商品種類に対しても、任意のプロパティ項目を任意の属性で定義できます。
図4: App Engineのデータ・ストアに登録する内容(プロパティ項目) |
[2]Eclipseのプロジェクト構成
それでは、ここから商品マスター登録におけるプログラム処理を解説します。最初に、Eclipseにおけるプロジェクトの構成を、簡単に説明します。
図5: プロジェクト構成 |
プロジェクト構成については、第1回でも説明しました。Low-Level APIを使う場合の構成を、あらためてサンプルで確認してみます。
①サーバー・サイドで記述する必要があるのは、Javaビーンズ(itemBean.java)だけです。JDOでは必須となるデータ・クラスの定義ファイルや、データ永続化用のPMF.javaは必要ありません。また、このプロジェクトでは、前回簡単に紹介したDWR(Direct Web Remoting)を使っているため、サーブレット(Servlet)の記述も必要ありません。
②このサンプルでは、図3(a、b、c)の登録画面処理でjQueryを使っています。このためのライブラリが配置されています。
③dwr.xmlは、DWRを使用する場合に必須となる定義ファイルです。
④このサンプルでは、登録画面のほかに、このあとで紹介する全件参照画面があります。それぞれ、メニュー画面のitemMenu.htmからアクセスするようになっています。
[3]サーバー側のプログラム
リスト1: addItemメソッド(Java Beans)
package jdoajax; import java.util.Hashtable; import com.google.appengine.api.datastore.DatastoreService; import com.google.appengine.api.datastore.DatastoreServiceFactory; import com.google.appengine.api.datastore.Entity; import com.google.appengine.api.datastore.Key; import com.google.appengine.api.datastore.KeyFactory; import java.util.List; import com.google.appengine.api.datastore.FetchOptions; import com.google.appengine.api.datastore.Query; public class itemBean { DatastoreService ds = DatastoreServiceFactory.getDatastoreService(); //(1) public String addItem(Hashtable query) { //(2) String kind = (String)query.get("kind"); Key itemNoKey = KeyFactory.createKey("itemMas", (String)query.get("itemNo")); //(3) Entity imas = new Entity(itemNoKey); //(4) imas.setProperty("itemName", (String)query.get("itemName")); //(5) imas.setProperty("type", (String)query.get("type")); //(5) imas.setProperty("price", Integer.parseInt((String)query.get("price"))); //(5) if(kind.equals("desktop")){ imas.setProperty("cpu",(String)query.get("cpu")); //(6) imas.setProperty("memory", (String)query.get("memory")); //(6) imas.setProperty("os", (String)query.get("os")); //(6) }else if(kind.equals("display")){ imas.setProperty("size", (String)query.get("size")); }else if(kind.equals("printer")){ imas.setProperty("papersize",(String)query.get("papersize")); imas.setProperty("resolution", (String)query.get("resolution")); } try{ ds.put(imas); //(7) return "登録成功"; } catch(Exception e){ return "登録不成功 " +e; } } :
リスト1は、Webクライアントから非同期通信で送られてくる商品マスター・データを、Low-Level APIを使用してデータ・ストアに永続化するプログラムです。基本的には、クライアントから送られてきたデータを使って登録処理を行うだけのシンプルな内容ですが、今回の主題であるプロパティ項目の可変性を利用しているので、その内容を中心に、コードを解説します。
[クライアントからの送信データ受信処理]
クライアントから送信されてきたデータは、(2)でハッシュテーブル(Hashtable)のqueryとして受信しています。このデータは、DWRを使ってクライアント側からJavascriptの連想配列として送信されています。このデータの受け側として、Hashtableを使用します。
[Low-level APIでの永続化処理]
Low-level APIでの永続化処理は、複雑ではありません。次のような処理の流れになります。
- ①キー(インデックス)を生成
【リスト1】の(3) - キーは、クライアントから送信されてきたitemNoをシーズに生成されています。このように、ユーザー・データを用いて生成されるキー(インデックス)は、カスタム・インデックスと呼ばれます。特にシーズとなる値を指定しなくても自動生成できますが、今回のようなアプリケーションでは値を指定したほうが良いでしょう。
- ↓
- ②キーを引数としたエンティティ・インスタンスを生成
【リスト1】の(4) - ↓
- ③インスタンスのsetPropertyメソッドでプロパティ名に対応した値をセット
【リスト1】の(5)と(6) - プロパティ名と値のセットは、(5)で各製品共通のプロパティ項目をセットし、(6)で製品種別ごとの個別項目をセットしています。個別項目のセットでは、if文で製品種別を判定し、対応するプロパティ項目を設定しています。前述したように、スキーマレスのApp Engineでは、任意のプロパティ項目をセットできます*3。
-
- [*3] ただし、エンティティのサイズには、1Mバイト以下という制約があります。
- ↓
- ④DatastoreServiceのインスタンスを生成し、インスタンスのputメソッドで永続化を実行
【リスト1】の(1)と(7) - ここまでで、準備はすべて終了です。最後に、永続化を実行します。永続化の実行は、(1)でDatastoreService(データ・ストア・サービス)のインスタンス「ds」を生成し、これに対するputメソッドで、引数にエンティティ・インスタンスのimasを指定して行ないます。データ・ストア・サービスのインスタンス生成はaddItemのメソッド外で最初に行われていますが、この背景には、インスタンスを各メソッドで共通に使うことで、インスタンス生成による負荷を軽減するという狙いがあります。
このサンプルの場合も、第1回で紹介したDWRのデバッグ画面を用いて、ビーンズ・メソッドのデータ登録機能を確認できます。ここでは説明を省略し、次ページからはクライアント側の画面処理について、簡単に説明します。