S-JIS[2010-05-21] 変更履歴

App Engine データストア

Google App Engine(GAE)のデータストアとは、データを保存・取得できるデータベース。


JDO・JPA

GAE標準のデータストアへのアクセス方法は、JDO(Java Data Objects)とJPA(Java Persistence API)を使用する。

これを使う為には、「src/META-INF/jdoconfig.xml」に永続化管理ファクトリーの設定(記述)が必要となる。
(デフォルトで書かれている)

   <persistence-manager-factory name="transactions-optional">
       <property name="javax.jdo.PersistenceManagerFactoryClass"
           value="org.datanucleus.store.appengine.jdo.DatastoreJDOPersistenceManagerFactory"/>
       <property name="javax.jdo.option.ConnectionURL" value="appengine"/>
       <property name="javax.jdo.option.NontransactionalRead" value="true"/>
       <property name="javax.jdo.option.NontransactionalWrite" value="true"/>
       <property name="javax.jdo.option.RetainValues" value="true"/>
       <property name="datanucleus.appengine.autoCreateDatastoreTxns" value="true"/>
   </persistence-manager-factory>

この永続化管理ファクトリーにアクセスする為のクラスも用意しておく(らしい)。

src/jp/hishidama/sample/gae/ex1/PMF.java:

package jp.hishidama.sample.gae.ex1;

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManagerFactory;

public class PMF {
	private static final PersistenceManagerFactory pmfInstance = JDOHelper.getPersistenceManagerFactory("transactions-optional");

	private PMF() {
	}

	public static PersistenceManagerFactory get() {
		return pmfInstance;
	}
}

データクラスの用意

データストアへの保存(永続化)は、Javaのオブジェクトをシリアライズしてファイルへ書き出すのと同じイメージ。

つまり、まず保存・取得する為のクラスを用意する必要がある。
(これ以外に事前に行う作業は無い。つまり、テーブル作成のcreate文を実行したりだとか、xmlファイルに定義を書くだとかは不要)

package jp.hishidama.sample.gae.ex1;

import java.util.Date;
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.datastore.Key;
import com.google.appengine.api.users.User;
@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Sample1Entity {

	@PrimaryKey
	private Key key;

	@Persistent
	private User author;

	@Persistent
	private String content;

	@Persistent
	private Date date;
	//コンストラクター
	public Sample1Entity(Key key, User author, String content, Date date) {
		this.key = key;
		this.author = author;
		this.content = content;
		this.date = date;
	}

〜セッター・ゲッターメソッド〜

	@Override
	public String toString() {
		return "key=[" + key + "], user=" + author + ", content=" + content + ",date=" + date;
	}
}

キーに当たるフィールドには@PrimaryKeyアノテーションを付ける。
その他の保存するフィールドには@Persistentアノテーションを付ける。
保存しないフィールドには@NotPersistentアノテーションを付ける。
どちらも付けないと、フィールドの型に応じてどちらかになるらしい。

データストアでは、保存するクラスの事をエンティティ、保存するフィールドの事をプロパティと呼ぶらしい。
プロパティーにはStringやint等が使える。→主な値型
また、それらのコレクション(List・Set)も使用できる(Mapは使用不可)。→コレクション


データの取得

import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.PersistenceManager;
	PersistenceManager pm = PMF.get().getPersistenceManager();
	try {
		Key key = KeyFactory.createKey(Sample1Entity.class.getSimpleName(), "123");

		Sample1Entity entity;
		try {
			entity = pm.getObjectById(Sample1Entity.class, key);
		} catch (JDOObjectNotFoundException e) {
			entity = null;
		}
	} finally {
		pm.close();
	}

データの保存

import javax.jdo.PersistenceManager;
	PersistenceManager pm = PMF.get().getPersistenceManager();

	Sample1Entity entity = 〜;

	try {
		pm.makePersistent(entity);
	} finally {
		pm.close();
	}

初めてエンティティーを作る場合、エンティティークラスを単純にnewで作ればよい。

そして必要に応じて各フィールド(プロパティー)に値をセットし、makePersistent()を呼び出す。
makePersistent()は、更新が終わるまでブロックされる(メソッド呼び出しが戻ってこない)。

PersistenceManagerから取得したエンティティーインスタンスのプロパティーに値をセットした場合、PersistenceManagerがクローズ(pm.close())された時点でデータストアに書き込まれる。(取得したエンティティーはPersistenceManagerにアタッチされている為)
こうした反映をしたくない場合、エンティティー用クラスの定義でデタッチを宣言(@PersistenceCapableアノテーションにdetachable属性を追加)すればいいらしい。

@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable="true")
public class Sample1Entity {
〜
	PersistenceManager pm = PMF.get().getPersistenceManager();
	pm.setDetachAllOnCommit(true);
	Sample1Entity entity;
	try {
		entity = pm.getObjectById(Sample1Entity.class, key);
	} finally {
		pm.close();
	}

オブジェクトの更新


データの削除

		pm.deletePersistent(entity);

GAEへ戻る / 技術メモへ戻る
メールの送信先:ひしだま