2015年4月22日水曜日

【GAE】初級実装編2 主キー検索 その2

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

現在はクラウド基盤「Google App Engine(以下、GAE)」の検索機能を検証中です。
今回は主キー検索を行います。

主キー検索


前回の振り返りになりますが、GoogleAppEngineは主キー検索には以下の2パターンがあります。

  • 自動インクリメント
  • 明示的にセット

このうち、自動インクリメント風なタイプでの検索を今回は実行します。

検索実行


では、「商品の主キー検索」を行うコントローラ「GetController」を作成します。
そのうち、商品の検索を行っている部分は以下です。

protected ShohinJet doResponse() throws Exception {

 ShohinDao dao = new ShohinDao();

 try {

  Key key = Datastore.createKey(Shohin.class, asInteger("id"));
  Shohin shohin = dao.get(key);

  logger.finer("取得結果:" + shohin.toString());

  ShohinJet jet = new ShohinJet(shohin);
  jet.setResponseCode(ResponseCode.SUCCESS);

  return jet;

 } catch (EntityNotFoundRuntimeException e) {

  throw new ErrorMessageException(ResponseCode.RECORD_NOT_FOUND, "商品");

 }
 
}

実は既に機能の独自フレームワーク化を行ってしまっておりまして、
私以外の人間には意味が分からないソースが含まれている件につきましては、申し訳ありませんがご了承下さい。

さて、上記ソースのうち、検索を行っている部分を抜き出しますと、以下になります。

ShohinDao dao = new ShohinDao();

Key key = Datastore.createKey(Shohin.class, asInteger("id"));
Shohin shohin = dao.get(key);

こうして見ると、何となくやり方がお分かりになるかと思います。

「キークラス」を作って検索するのですね。

キークラス検索

例えば、普通のデータベースクラスの場合、「id=4」であれば、以下のようなSQLを発行します。

SELECT *
FROM SHOHIN
WHERE ID = 4

GoogleAppEngineの場合はキークラスで検索するのです。
キークラスは以下のように「Datastore.createKey」を使って生成出来ます。

Key key = Datastore.createKey(Shohin.class, asInteger("id"));

これで「商品テーブルの主キー」というクラスが生成出来たわけですね。
簡単です。

様々な主キー検索


基本的には上記の検索で要件は足りますが、どうやらSlim3&GAEには色々と便利機能も備わっているようです。
Eclipeでメソッドを調べてみると以下が出てきました。


これらの機能も見ていこうかと思います。

get(List<key> keys)


キーをListで複数渡せるようです。 要するに内部でgetを連発しているのでしょうね。
さて、普通のシステム開発の場合、こういう風にSQLを何度も発行すると負荷が高くなってしまってお薦め出来ません。 潔く範囲検索SQLを発行するのが正解でしょう。
しかし、GAEは大量不可に強いシステムですので、多少こんな風に連発処理してしまっても問題にはなりません。 余程件数が多いでもない限り、ありがたく便利機能を使わせて頂きましょう。

getOrNull(Key key)

エンティティを取得するか、nullを返すという意味です。
最初にご紹介した普通の「get」で検索結果が取得出来ない場合、そのままだとnullが返ってくるのではなくて「EntityNotFoundRuntimeException」が発生します。
それを回避してくれるのがgetOrNullなわけです。

  • get:基本的に取得出来ると想定する場合の主キー検索
  • getOrNull:検索出来ない場合を許容する場合の主キー検索

こういう使い分けになるのです。

getAsync(Key key)


Async。非同期検索機能も備わっているようです。
これはJava本体のマルチスレッドの機能ですね。

処理速度のチューニングを突き詰める為の機能です。

例えば、以下みたいな感じに使います。

/*
* DBの検索開始
* バックエンドで検索するが、この時点で取得が完了するわけではない。
*/
Future<shohin> shohinFuture = dao.getAsync(key);

logger.finer("先にエンティティをしない処理を進めておく。");
logger.finer("先にエンティティをしない処理を進めておく。");
logger.finer("先にエンティティをしない処理を進めておく。");

/*
* エンティティの取得。
* この時点でエンティティを取得出来る。
*/
Shohin shohin = shohinFuture.get();

/*
* エンティティを使った処理を行う
*/
ShohinJet jet = new ShohinJet(shohin);

普通の「get」の場合、取得に処理時間が必要になります。(まあ、一瞬ではありますが)
普通のgetでは取得完了までその場で待機しなければなりませんが、「getAsync」であれば待機せずに先に進みます。

そしてエンティティを使用しなくても良い部分の処理を先に実行しておいて、
後から「get();」により取得する。

これによりDB検索の待ち時間を短縮出来るわけです。

まあ、GAEは元々が高速なので1件だけのgetだとやる価値が無いかもしれませんが、大量処理を行う場合は、こういう機能を使ってチューニングしていきたいものです。

終わりに


引き続きGAEについてご紹介します。