2010年4月10日土曜日

GoogleAppEngine-JDOQLクエリフィルタの使い方

前回のGoogleAppEngine-GWTの使い方の続きです

今回はGWT UIとサーバーを連携させる前に、JDOQLの高度なフィルタ機能を少し説明します。

JDOQLはSQLのような構文でGoogleのストレージを操作することができます。基本的には文字列で条件文を記述すれば操作はできますが、JDOQLにJavaのクラスを混ぜたいときがあります。例えば、オブジェクト内にDateクラスが含まれていて、ある日時以降のデータを検索したい場合です。
そういったときに、JDOQLのクエリフィルタAPIを使用し、高度な条件を指定します。今回は、「指定した位置から指定個数検索する」と「指定時間以降のデータを指定個数検索する」の二つの機能を作ってみます。


Tweet.java
----------------------------------


package com.devtter.server.model;

import java.util.Date;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
import com.google.appengine.api.users.User;

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Tweet {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;

@Persistent
private User googleId;

@Persistent
private String content;

@Persistent
private Date date;
}


TweetDAO.java
----------------------------------

package com.devtter.server.model;

import java.util.List;
import java.util.Date;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;


public class TweetDAO {

/**
* 指定した位置から指定個数のつぶやきを検索します
*
*
* @param start 開始位置
* @param num 個数
* @return Tweetクラスのリスト
*/
public static List find(int start, int num) {
PersistenceManager pm = PMF.get();
String query = "select from "
+ Tweet.class.getName()
+ " order by date desc range "
+ start + "," + num;
List tweets = (List) pm.newQuery(query).execute();
pm.detachCopyAll(tweets);
pm.close();
return tweets;
}

/**
* 指定時間以降につぶやかれたTweetを検索します。
*
* @param starttime 開始時間
* @param num 個数
* @param desc 降順にするかどうか。
* @return Tweetクラスのリスト
*/
public static List findBeforeStartTime(long starttime, int num, boolean desc) {
PersistenceManager pm = PMF.get();
Date dateStartTime = new Date(starttime);
Query query = pm.newQuery(Tweet.class);
query.declareImports("import java.util.Date");
query.declareParameters("Date ParamStartDate");
query.setFilter("date > ParamStartDate");
if(desc)
query.setOrdering("date desc");
else
query.setOrdering("date asc");

query.setRange(0,num);

List tweets
= (List) pm.newQuery(query).execute(dateStartTime);
pm.detachCopyAll(tweets);
pm.close();
return tweets;
}
}


一つ目のfind関数では、クエリフィルタAPI使わず文字列で検索文を作成し、実効しています。この処理はおおよそ下記のような文字列になります。

select from com.devtter.server.model.Tweet order by date desc range 0, 5

次にfindBeforeStartTime関数ではTweetクラスのDateオブジェクトが指定した日時以降かを条件に検索しています。この処理をするにはまず、declareImports関数でDate型をimportします。これによりQueryクラス内でjava.util.Dateクラスが使えるようになります。次にdeclareParameters関数で変数を宣言します。そして、setFilter関数で条件判定を指示しています。ここで指定しているParamStartDate変数に値を代入するには、検索実行時のexecute関数の引数に変数を代入します。

Twitterのようなアプリケーションを実際に作り込むと、必ず高度な条件での検索が必要になるのでクエリフィルタは重要な機能ですね。
なお今回のプログラムはおおよそ下記にあります。
http://code.google.com/p/devtter/source/browse/trunk/devtter/src/com/devtter/server/model/TweetDAO.java

0 件のコメント:

コメントを投稿