【slim3】永続化対象としての”Model”
GAE ではデータを、”BigTable”という key-value ベースの DB(key-value store)で管理します。
この”BigTable”へ永続化するクラスとして、slim3 では”Model”というクラスを定義・使用します。
1.Modelの作成方法
前回の記事の、”gen-model”をご確認下さい。
2.Modelの概要
Model は、一言でいうと JavaBeans です。
基本的に、永続化対象のデータ項目をインスタンス変数として定義し、その getter/setter を定義すればOK、という作りになっています。
3.Modelの詳細
Model は、slim3 や BigTable で使用されることから、単なる JavaBeans には見られない以下のような特徴を持ちます。
※以下は、Model 生成時に自動的に用意されます。
(1)java.io.Serializable を implement している
あわせて、定数 serialVersionUID が定義されます。
(2)クラス定義に @Model アノテーションがつく
(3)主キーを持つ
- com.google.appengine.api.datastore.Key 型の変数 key を持ちます。
- Model クラスには、主キーが1つ必要。
- 同変数には、@Attribute(primaryKey=true) アノテーションがつきます。
- org.slim3.datastore.Attribute クラスを参照。
(4)楽観チェック用の version を持つ
- Long 型の変数 version を持ちます。
- 同変数には、@Attribute(version = true) アノテーションがつきます。
- org.slim3.datastore.Attribute クラスを参照。
(5)schemaVersion を持つ。
- Integer 型の変数 schemaVersion を持ちます。
- ※意味がよく分からないです。。。
- GAE バージョンアップに備え…という情報があるが、裏がまだとれていないです。
※2010/02/07(日)追記
「データ定義」のバージョンを保持する項目(SVN のバージョン番号みたいなもの)。
例えばデータ項目を追加した場合に、古い schemaVersion のレコードに一律にデフォルト値をセットする、というような使い方ができる。
※bluerabbitさん、ご指摘ありがとうございました。
4.データ項目の追加方法
永続化対象のデータ項目を追加する方法は、次の通りです。
ちなみに、使用できるデータ型は、こちらに定義されています。
なお、変数としては定義したいけれども永続化対象にはしたくない!という時には、変数定義に @Attribute(persistent=false) のアノテーションを定義すればOKです。
データ項目の追加例は、当記事の一番下にある定義例をご確認下さい。
5.Metaクラスの自動生成
Model クラスをコンパイルまたは実行すると、<プロジェクトルート>/.apt_generated/<アプリケーションのルートパッケージ>/meta 以下に、
ここに、Model の詳細実装が入っています。
データ項目を追加・変更してコンパイルすると、この Meta クラスが自動的に修正されます。
6.単体テスト
IndexController や Service とは異なり、特別なクラスの継承は不要です。
テスト内容としては、普通の JavaBeans のテストで問題ありません。
ただ1点だけ、テスト用に Key を生成する方法がわかりません。
無理やり Key を生成しようとすると、以下のエラーが出てしまいます。
java.lang.NullPointerException: No API environment is registered for this thread.
これについては、引き続き調査をしていきます。
※2010/02/07(日)追記
テスト実施用に環境設定を行う必要がある。
暫定的な対応としては、org.slim3.tester.LocalServiceTestCase を extend すると回避可能。
(後日、正式な調査・報告をします。)
※bluerabbitさん、ご指摘ありがとうございました。
7.【参考】Model の定義例
「質問」と「回答」の2つのフィールドを持つ、Q&A の Model を作成する例を以下にあげます。
package xxx.yyy.model.qanda; import java.io.Serializable; import org.slim3.datastore.Attribute; import org.slim3.datastore.Model; import com.google.appengine.api.datastore.Key; @Model public class QAndA implements Serializable { // fields private static final long serialVersionUID = 1L; @Attribute(primaryKey = true) private Key key; @Attribute(version = true) private Long version; private Integer schemaVersion = 1; // 追加したフィールド private String question; private String answer; // getter public Key getKey() { return this.key; } public Long getVersion() { return this.version; } public Integer getSchemaVersion() { return this.schemaVersion; } // 追加した getter public String getQuestion() { return this.question; } // 追加した getter public String getAnswer() { return this.answer; } // setter public void setKey(Key key) { this.key = key; } public void setVersion(Long version) { this.version = version; } public void setSchemaVersion(Integer schemaVersion) { this.schemaVersion = schemaVersion; } // 追加した setter public void setQuestion(String question) { this.question = question; } // 追加した setter public void setAnswer(String answer) { this.answer = answer; } }