2012年8月25日土曜日

[AppEngine] JDO でデータストアを使う(準備編)

アプリがデプロイして動くようになったので データストアを使ってみる。
App Engine のデータストアを使用するには、 JDO(Java Data Objects)、 JPA(Java Persistence API)、 および、App Engine 独自の Low Level API を使用する方法がある。

Google App Engine の スタートガイドでは JDO を使っている のでまずは JDO を使ってやってみる。


PersistenceManagerFactory


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

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

JDO でデータストアを操作する PersistenceManager は PersistenceManagerFactory から取得するのだが、 PersistenceManagerFactory 自体の生成がコストが高いらしく一度生成した PersistenceManagerFactory は使いまわすらしい。( by スタートガイド

getPersistenceManagerFactory で指定した "transactions-optional" は、Eclipse のプラグインが自動生成した jdoconfig.xml に以下のように記載されている。

<?xml version="1.0" encoding="utf-8"?>
<jdoconfig xmlns="http://java.sun.com/xml/ns/jdo/jdoconfig"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:noNamespaceSchemaLocation="http://java.sun.com/xml/ns/jdo/jdoconfig">

  <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>
</jdoconfig>

特にいじる必要もないのでこのまま。
persistence.xml にも transactions-optional という名前の persistence-unit が定義されているが、 たぶんこちらは JPA を使う際のファイルなので今回は関係ないと思う。


データクラスの準備


とりあえずこんなクラスを用意した。

package xawa99.test.HelloApp;
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;

@PersistenceCapable(identityType=IdentityType.APPLICATION)
public class MyData {

    @PrimaryKey
    @Persistent(valueStrategy=IdGeneratorStrategy.IDENTITY)
    private Long id;

    @Persistent
    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }    
}

@PersistenceCapable アノテーションで永続化対象クラスであることを宣言する。
@Persistent アノテーションが付与されたフィールドが永続化対象のフィールド、 @PrimaryKey アノテーションが付くと主キーになって、PersistenceManager#getObjectById で指定できるようになる。

フィールドに @Persistent(valueStrategy=IdGeneratorStrategy.IDENTITY) を付与するとデータストア側で勝手に値を設定してくれるので生成時に値を指定する必要がなくなる。

IdGeneratorStrategy には他にも INCREMENT という指定もあるのだが、こちらは Application Engine でサポートしていないようで

  There is no available value generator for strategy "increment" for this datastore. Please consult the documentation for details of which generators are available.

とエラーになってしまった。INCREMENT と NATIVE はエラー、SEQUENCE、UUIDHEX と UUIDSTRING は OK だった。ただし、IDENTITY と SEQUENCE は Long型フィールドに使えるが、UUIDHEX と UUIDSTRING はフィールドを String にしないといけない。

valueStrategy は 主キーフィールドでなくても値の自動付与はされるのだが、IdGeneratorStrategy.IDENTITY を指定した場合には自動付与されない。これは主キー専用のようだ。
SEQUENCE、UUIDHEX、UUIDSTRING では主キーでなくとも自動生成した値が付与される。


0 件のコメント:

コメントを投稿