[バファリンズ]
半分はやさしくないものでできています
- 2010-12-28 bufferings
- 2010-12-28 soundTrick
- 2010-06-14 bufferings
- 2010-06-14 hiro_nemu
- 2010-05-10 bufferings
|
bufferings
[バファリンズ] 半分はやさしくないものでできています カテゴリー
カレンダー
最近のコメント
リンク
|
2009-11-23Slim3 Datastore を日本語に訳してみたSlim3 Datastore を日本語に訳してみた | | 2010-01-17 日本語訳はgoogle-sitesに移行しました。今後はそちらに最新の内容を適用していきます。 http://sites.google.com/site/slim3documentja/ ちょっと前にSlim3 Datastore のドキュメントが公開された。 メモしつつ。つぶやきを垂れ流しつつ。読んだ。で。訳してみた。 何かちょっと違和感を感じるとか。ここどういうこと?とか。変だよ。違うよってところがあったら。 つっこんでほしいです。お願いします。 ひがさんをはじめ。 色々教えてくださった僕のTLの素敵な皆さんに深く感謝します。 ちょっと注意点Slim3 Datastore のことは「Slim3 Datastore」と英語で書いてます。 App Engine のデータストアは「データストア」とカタカナで書いてます。 目次
更新
Slim3 DatastoreSlim3 Datastore を日本語に訳してみた | | http://sites.google.com/site/slim3appengine/slim3-datastore Slim3 Datastore は Datastore Low level API のタイプセーフな薄いラッパーです。Low level API は Bigtable に特化しているので JDO/JPA よりも高速に動作し、JDO/JPA よりも簡単に学ぶことができます。 Slim3のタイプセーフなクエリはこんな感じ。 EmployeeMeta e = new EmployeeMeta(); List<Employee> list = Datastore.query(e) .filter(e.job.equal("ANALYST"), e.salary.greaterThan(5000)) .sort(e.name.asc) .asList(); EmployeeMeta のようなモデルのメタデータは Annotation Processing Tool によって自動的に生成されます。 同じことを JDO のクエリでやるとこんな感じ。 List<Employee> list = null; PersistenceManager pm = PMF.get().getPersistenceManager(); try { Query query = pm.newQuery(Employee.class); query.setFilter("job == \"ANALYST\") && salary > 5000"); query.setOrdering("name asc"); list = (List<Employee>) query.execute(); list = (List<Employee>) pm.detachCopyAll(list); } finally { pm.close(); } return list; JDO のクエリのように文字列を使ってクエリを書くとプロパティ名をリファクタリングしてもコンパイラーは何のエラーも表示しません。 でも Slim3 Datastore のタイプセーフなクエリを使うと、例えば"salary"プロパティの名前を変更したらコンパイラーは「え?"salary"とかもう知らんよ」と教えてくれます。APT によってモデルのメタデータが再生成されるからです。 Slim3 Datastore はエンティティとモデルの間のマッピングロジックを、コンパイル時にモデルメタのソースコードに書き出します。 次のコードは BarMeta の一部です。 @Override public slim3.demo.model.Bar entityToModel( com.google.appengine.api.datastore.Entity entity) { slim3.demo.model.Bar model = new slim3.demo.model.Bar(); model.setKey(entity.getKey()); model.setSortValue((java.lang.String) entity.getProperty("sortValue")); return model; } @Override public com.google.appengine.api.datastore.Entity modelToEntity( java.lang.Object model) { slim3.demo.model.Bar m = (slim3.demo.model.Bar) model; com.google.appengine.api.datastore.Entity entity = null; if (m.getKey() != null) { entity = new com.google.appengine.api.datastore.Entity(m.getKey()); } else { entity = new com.google.appengine.api.datastore.Entity("Bar"); } entity.setProperty("sortValue", m.getSortValue()); return entity; } Slim3 Datastore はエンティティとモデルのマッピングに実行時リフレクションを必要としないので JDO よりも高速に動作します。 10,000件のシンプルなエンティティを取得するのに、Slim3 は約4,000ミリ秒、JDO は約12,000ミリ秒かかります。 オンラインデモ を見てください。 概要Slim3 Datastore を日本語に訳してみた | | http://sites.google.com/site/slim3appengine/slim3-datastore/overview Google App Engine データストアは強固でスケーラブルなウェブアプリケーション用ストレージを提供します。 そのデータストアは
データストアの紹介http://sites.google.com/site/slim3appengine/slim3-datastore/overview/introducing-the-datastore App Engine データストアはデータオブジェクトを保存したり、クエリを実行したりします。
データストアは単一のトランザクションで複数の操作を実行することができ、いずれかの操作が失敗した場合にはトランザクション全体をロールバックすることができます。これは、複数のユーザーが同じデータオブジェクトに対して同時にアクセスまたは操作をする可能性のある分散ウェブアプリケーションにとって特に有用です。 従来のデータベースとは違って、データストアは非常に大きなデータセットのスケーリングを扱うために、分散アーキテクチャを使用しています。App Engine のアプリケーションはデータオブジェクト間の関連を記述したり、クエリのためのインデックスを定義したりすることによって、データがどのように分散されるかを最適化することができます。 App Engine データストアは強い 一貫性 を持っていますが、リレーショナルデータベースではありません。データストアのインターフェイスはこれまでのデータベースと同じ特徴を多く持っていますが、データストアには独自の特徴があり、自動スケーリング機能を利用するためにはデータの設計方法や扱い方が変わってくるということを暗に意味しています。 データモデリングhttp://sites.google.com/site/slim3appengine/slim3-datastore/overview/data-modeling データストアのエンティティは「スキーマレス」です。同じ kind の二つのエンティティが同じプロパティを持ったり、同じプロパティに対して同じデータ型を使ったりする必要はありません。必要に応じてエンティティがスキーマに従うことをアプリケーションが保障する必要があります。そのため Slim3 には簡単にエンティティをスキーマに従わせることができるようなデータモデリング機能があります。 Slim3 では「モデル」によってエンティティの kind を定義します。
@Model public class Employee { @Attribute(primaryKey = true) private Key key; private String name; private String role; private Date hireDate; private Boolean newHireTrainingCompleted; ... } Employee e = new Employee(); e.setRole("manager"); e.setHireDate(new Date()); Datastore.put(e); Slim3 Datastore API はクエリのインターフェイスを提供します。クエリはモデルクラスのインスタンスの形式でエンティティを返します。そしてそのモデルは変更したりデータストアに戻したりすることができます。 EmployeeMeta のようなモデルのメタデータは Annotation Processing Tool によって自動的に生成されます。 EmployeeMeta e = new EmployeeMeta(); List<Employee> employees = Datastore.query(e).asList(); for (Employee emp : employees) { emp.setNewHireTrainingCompleted(true); } Datastore.put(employees); エンティティとプロパティhttp://sites.google.com/site/slim3appengine/slim3-datastore/overview/entities-and-properties App Engine データストア内のデータオブジェクトは「エンティティ」と呼ばれます。エンティティには1つ以上の「プロパティ」があります。プロパティは整数・浮動小数・文字列・日付・バイナリデータなどのサポートされたデータ型の中の1つの型の値に名前をつけたものです。 各エンティティには、そのエンティティを一意に識別する「キー」も含まれます。最も単純なキーは「kind」とデータストアによって与えられた一意の数値 ID を持っています。ID にはアプリケーションで設定した文字列を使用することもできます。 アプリケーションはキーを使用したり、エンティティのプロパティに合わせたクエリを実行したりして、データストアからエンティティを取得することができます。 クエリは
リレーショナルデータベースと違って App Engine データストアでは、ある kind の全エンティティが同じプロパティを持つ必要はありません。しかし Slim3 を使用すれば特定のデータモデルに従わせることができます。 プロパティは複数の値を持つことができます。
クエリとインデックスhttp://sites.google.com/site/slim3appengine/slim3-datastore/overview/queries-and-indexes App Engine データストアのクエリは指定された kind (データクラス) の全てのエンティティに対して処理を行います。クエリにはエンティティのプロパティ値やキーに対する0個以上のフィルタと、0個以上のソート順を指定することができます。 あるエンティティがクエリの結果として返されるのは
場合です。 データストアの全てのクエリはインデックスを使用します。
この仕組みは広い範囲のクエリをサポートし多くのアプリケーションに適しています。しかし、他のデータベース技術で慣れ親しんでいるクエリの中にはサポートされないものもあります。 トランザクションとエンティティグループhttp://sites.google.com/site/slim3appengine/slim3-datastore/overview/transactions-and-entity-groups トランザクションは
のどちらかであることを保障します。これによってエンティティのデータの一貫性が保障されます。 トランザクション API を使って、単一トランザクションで複数のアクションをエンティティに適用することができます。例えば、あるオブジェクトのカウンターをインクリメントしたいとしましょう。そうするためには、まずカウンターの値を取得して、新しい値を計算して、保存する必要があります。トランザクションを使用しなかったら、値を読み込んでから更新するまでの間に別のプロセスがカウンターをインクリメントしてしまい、アプリケーションがそのインクリメントされた値を上書き更新してしまうということが起こりえます。読み込み、計算、書き込みを単一トランザクション内で行うことで、他のプロセスの影響を受けずにカウンターをインクリメントすることができます。 単一トランザクションで複数のエンティティに対して変更を加えることもできます。そのためには、トランザクション内で複数のエンティティを保存することができるように、あらかじめどのエンティティが一緒に更新されるのかを App Engine に知らせておく必要があります。それは、あるエンティティを作成するときに別のエンティティと同じ「エンティティグループ」に所属することを宣言するということです。単一トランザクション内で取得・作成・更新・削除を行う全てのエンティティは同じエンティティグループに所属していなければなりません。 エンティティグループはエンティティ間の関連の階層構造によって定義されます。
データストアはトランザクションを扱うのに「楽観的並列処理」を行います。あるアプリケーションのインスタンスがエンティティグループのエンティティに変更を適用している間は、グループ内のエンティティに対するその他の更新は全てすぐに失敗します。アプリケーションは更新されたデータに対してトランザクションの適用を再実行することができます。 Slim3 Datastore の使用Slim3 Datastore を日本語に訳してみた | | http://sites.google.com/site/slim3appengine/slim3-datastore/using-slim3-datastore Slim3 Datastore は Datastore Low level API のタイプセーフな薄いラッパーです。Slim3 Datastore には Java オブジェクトに注釈をつけたり、クエリでオブジェクトを検索したり、トランザクションを使用してデータストアとやりとりをしたりするためのインターフェイスがあります。 注:Eclipse3.4 に pleiades をあてて訳しました。画面ショットは Slim3 のドキュメントのものをコピーして使わせていただいてます。 Slim3 Datastore の新規プロジェクトを作成するための設定1. 最新の Slim3 blank project(slim3-blank-xxx.zip) を ダウンロード して解凍します。 2. slim3-blank プロジェクトをエクリプスのワークスペースにインポートします。 3. エクリプスにテスト用の設定を行います。 ウィンドウメニュー > 設定 > Java > コード・スタイル > インポートの編成 で「.* に必要な静的インポート数」を1にします。 ウィンドウメニュー > 設定 > Java > エディタ > コンテンツ・アシスト > お気に入り で「新規タイプ」ボタンをクリックして
を追加します。 ウィンドウメニュー > 設定 > 一般 > ワークスペース で「自動的にリフレッシュ」をチェックします。 4. プロジェクト名を「tutorial」(好きな名前)に変更します。(リファクタリング > 名前変更) 5. slim3-gen-xxx.jar を 注釈処理のファクトリー・パスに追加します。 プロジェクトプロパティダイアログで、Java コンパイラー > 注釈処理 > ファクトリー・パス を選択します。 slim3-gen-xxx.jar をパスに追加します。 既存プロジェクトで Slim3 Datastore を使用するための設定1. 最新の Slim3 blank project(slim3-blank-xxx.zip) を ダウンロード して解凍します。 2. war/WEB-INF/lib/slim3-xxx.jar を "あなたのプロジェクト"/war/WEB-INF/lib にコピーします。 3. slim3-xxx.jar を Java のビルドパスに追加します。 4. エクリプスにテスト用の設定を行います。 ウィンドウメニュー > 設定 > Java > コード・スタイル > インポートの編成 で「.* に必要な静的インポート数」を1にします。 ウィンドウメニュー > 設定 > Java > エディタ > コンテンツ・アシスト > お気に入り で「新規タイプ」ボタンをクリックして
を追加します。 ウィンドウメニュー > 設定 > 一般 > ワークスペース で「自動的にリフレッシュ」をチェックします。 5. slim3-gen-xxx.jar を 注釈処理のファクトリー・パスに追加します。 プロジェクトプロパティダイアログで、Java コンパイラー > 注釈処理 > ファクトリー・パス を選択します。 slim3-gen-xxx.jar をパスに追加します。 6. DatastoreFilter を war/WEB-INF/web.xml に定義します。このフィルターは例外が発生した際に自動的にロールバックを行います。 <filter> <filter-name>datastoreFilter</filter-name> <filter-class>org.slim3.datastore.DatastoreFilter</filter-class> </filter> <filter-mapping> <filter-name>datastoreFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> </filter-mapping> モデルとテストの作成プロジェクトフォルダ直下の build.xml ファイルをダブルクリックして開きます。 アウトラインビューで model-controller タスクを右クリックをして 「実行 > 1 Ant ビルド」を選択します。 Ant の入力ダイアログで"お好きな名前"を入力して、OK ボタンをクリックします。 プロジェクトが自動的にリフレッシュする設定になっていない場合は ウィンドウメニュー > 設定 > 一般 > ワークスペース で「自動的にリフレッシュ」をチェックしてください。 "お好きな名前"に"Message"と入力した場合は、"src/tutorial/model/Message.java" と "test/tutorial/model/MessageTest.java" が生成されます。 "src/tutorial.model/Message.java" を見てみましょう。 Message.java package tutorial.model; import java.io.Serializable; import com.google.appengine.api.datastore.Key; import org.slim3.datastore.Attribute; import org.slim3.datastore.Model; @Model public class Message implements Serializable { private static final long serialVersionUID = 1L; @Attribute(primaryKey = true) private Key key; @Attribute(version = true) private Long version; private Integer schemaVersion = 1; /** * Returns the key. * * @return the key */ public Key getKey() { return key; } /** * Sets the key. * * @param key * the key */ public void setKey(Key key) { this.key = key; } /** * Returns the version. * * @return the version */ public Long getVersion() { return version; } /** * Sets the version. * * @param version * the version */ public void setVersion(Long version) { this.version = version; } /** * Returns the schema version. * * @return the schema version */ public Integer getSchemaVersion() { return schemaVersion; } /** * Sets the schema version. * * @param schemaVersion * the schema version */ public void setSchemaVersion(Integer schemaVersion) { this.schemaVersion = schemaVersion; } } "test/tutorial.model/MessageTest.java" を見てみましょう。 MessageTest.java package tutorial.model; import org.junit.Test; import static org.junit.Assert.*; import static org.hamcrest.CoreMatchers.*; public class MessageTest { private Message model = new Message(); @Test public void test() throws Exception { assertThat(model, is(notNullValue())); } } "MessageTest.java"のテストを実行します。結果はグリーン( OK )になります。 データクラスの定義Slim3 Datastore を日本語に訳してみた | | http://sites.google.com/site/slim3appengine/slim3-datastore/defining-data-classes Slim3 Datastore を使うと、普通の Java データオブジェクト(POJOと呼ばれたりするもの)をデータストアに保存できます。Slim3 Datastore によって永続化されたオブジェクトは、データストア内のエンティティになります。モデルインスタンスの保存方法や再生成の方法を Slim3 Datastore に指定するためにアノテーションを使用します。 クラスとフィールドのアノテーションhttp://sites.google.com/site/slim3appengine/slim3-datastore/defining-data-classes/annotations Slim3 Datastore によって保存されたオブジェクトは App Engine データストア内のエンティティになります。エンティティの kind はクラスの単純名から取得します(内部クラスはパッケージ名を除いて $ のパスを使用します)。クラスの永続化フィールドがエンティティのプロパティを表し、大文字小文字をそのままにしたフィールド名がエンティティのプロパティ名になります。 Java クラスをモデルとして宣言するためには @Model アノテーションをつけます。 import org.slim3.datastore.Model; @Model public class Employee { // ... } データクラスのフィールドはデータストアに保存されます。永続化フィールドは getter と setter メソッドを持たなければなりません。 import java.util.Date; // ... private Date hireDate; public Date getHireDate() { return hireDate; } public void setHireDate(Date hireDate) { this.hireDate = hireDate; } 永続化しないフィールド(データストアに保存したりデータストアから取得したりしないフィールド)を宣言するためには @Attribute(persistent = false) アノテーションをつけます。 import java.util.Date; import org.slim3.datastore.Attribute; // ... @Attribute(persistent = false) private Date hireDate; フィールドの型は次に示す型のいずれかです。詳細は後述します。
データクラスは、対応するデータストアエンティティに主キーを保存するためのフィールドを1つ持たなければなりません。キーのフィールドは com.google.appengine.api.datastore.Key でなければなりません。キーには @Attribute(primaryKey = true) アノテーションを使用します。 import com.google.appengine.api.datastore.Key; import org.slim3.datastore.Attribute; // ... @Attribute(primaryKey = true) private Key key; // ... accessors ... モデルのメタデータhttp://google.com/site/slim3appengine/slim3-datastore/defining-data-classes/meta-data-of-model モデルを定義したら Annotation Processing Tool によってモデルのメタデータが自動的に生成されます。例えば slim3.demo.model.Employee モデルを定義したら slim3.demo.meta.EmployeeMeta が生成されます。モデルの定義に変更を加えたら、モデルのメタデータも再生成されます。 モデルのメタデータにはモデルとエンティティのマッピングメソッドが含まれています。 @Override public slim3.demo.model.Foo entityToModel(com.google.appengine.api.datastore.Entity entity) { slim3.demo.model.Employee model = new slim3.demo.model.Employy(); model.setKey(entity.getKey()); model.setFirstName((java.lang.String) entity.getProperty("firstName")); model.setLastName((java.lang.String) entity.getProperty("lastName")); model.setHireDate((java.util.Date) entity.getProperty("hireDate")); return model; } @Override public com.google.appengine.api.datastore.Entity modelToEntity(java.lang.Object model) { slim3.demo.model.Employee m = (slim3.demo.model.Employee) model; com.google.appengine.api.datastore.Entity entity = null; if (m.getKey() != null) { entity = new com.google.appengine.api.datastore.Entity(m.getKey()); } else { entity = new com.google.appengine.api.datastore.Entity("Employee"); } entity.setProperty("firstName", m.getFirstName()); entity.setProperty("lastName", m.getLastName()); entity.setProperty("hireDate", m.getHireDate()); return entity; } Slim3 はマッピングメソッドをコンパイル時に生成して実行時にはそのメソッドを使用するので、マッピングに実行時リフレクションを必要としません。そのため、 Slim3 は他のフレームワークよりも高速に動作します。 主な値型http://sites.google.com/site/slim3appengine/slim3-datastore/defining-data-classes/core-value-types データストアは以下の主な値型をサポートします。
シリアライズ可能なオブジェクトシリアライズ可能なクラスのインスタンスは Blob 値として保存することができます。 Slim3 Datastore では、シリアライズ可能なクラスのインスタンスを Blob 値として保存する場合はフィールドに @Attribute(lob = true) アノテーションをつけます。 Blob 値はインデックスづけできないのでクエリのフィルタやソート順に使用することはできません。 次に示すのはシンプルなシリアライズ可能クラスの例です。ファイルの内容とファイル名とMIMEタイプを持った、ファイルを表すクラスです。 import java.io.Serializable; public class DownloadableFile implements Serializable { private static final long serialVersionUID = 1L; private byte[] content; private String filename; private String mimeType; // ... accessors ... } シリアライズ可能クラスのインスタンスを Blob 値としてプロパティに保存する場合は、クラス型のフィールドを宣言して @Attribute(lob = true) アノテーションをつけます。 import DownloadableFile; import org.slim3.datastore.Attribute; // ... @Attribute(lob = true) private DownloadableFile file; バイト配列http://sites.google.com/site/slim3appengine/slim3-datastore/defining-data-classes/array-of-bytes バイト配列は Blob 値として保存することができます。Slim3 Datastore では、バイト配列を Blob 値として保存する場合はフィールドに @Attribute(lob = true) アノテーションをつけます。Blob 値はインデックスづけできないのでクエリのフィルタやソート順に使用することはできません。 @Attribute(lob = true) private byte[] bytes; 長いテキスト文字列http://sites.google.com/site/slim3appengine/slim3-datastore/defining-data-classes/long-text-string 長いテキスト文字列(500バイト以上)は Text 値として保存することができます。Slim3 Datastore では、長いテキスト文字列を Text 値として保存する場合はフィールドに @Attribute(lob = true) アノテーションをつけます。Text 値はインデックスづけできないのでクエリのフィルタやソート順に使用することはできません。 @Attribute(lob = true) private String content; コレクションhttp://sites.google.com/site/slim3appengine/slim3-datastore/defining-data-classes/collections データストアのプロパティは1つ以上の値をもつことができます。Slim3 Datastore では、これはコレクション型の単一フィールドによって表されます。コレクションはコア型の1つかシリアライズ可能クラスからなります。以下のコレクション型がサポートされています。
フィールドが List として宣言されている場合は、 Slim3 Datastore は ArrayList を返します。 Set で宣言されている場合は HashSet を、 SortedSet で宣言されている場合は TreeSet を返します。 コレクションはインデックスづけすることができるので、クエリのフィルタやソート順に使用することができます。 例えば、 List<String> 型のフィールドは0個以上の文字列値としてプロパティに保存されます。その1つ1つはリストの値です。 import java.util.List; // ... private List<String> favoriteFoods; // ... accessors ... 配列はコレクションとしてはサポートされていません。つまり配列はインデックスづけされず、クエリのフィルタやソート順で使えません。配列をデータストアに保存したければそのフィールドをシリアライズ可能なクラスとして指定するべきです。 import org.slim3.datastore.Attribute; // ... @Attribute(lob = true) private String[] favoriteFoods; // ... accessors ... インデックスづけされないプロパティデフォルトでは App Engine データストアはエンティティの全てのプロパティ(Blob と Text 以外)に対してそれぞれインデックスのレコードを2つずつ作成します(single property index を昇順・降順の2つ作成)。このインデックスレコードのおかげで、複合インデックスを作成せずにそのプロパティを含む様々なクエリを実行することができます。 このインデックスは書き込みに時間がかかりディスク領域を使用します。あるプロパティをフィルタやソートで決して使用しないことが完全に明らかなのであれば、デフォルトのインデックスづけを中止することができます。 例 @Attribute(unindexed = true) private String unindexedString; @Attribute(unindexed = true) List<String> favoriteColorList = new ArrayList<String>(); // ... モデルの属性とエンティティのプロパティApp Engine データストアでは「プロパティがないエンティティ」と「プロパティに null が入っているエンティティ」が区別されます。 一方 Slim3 Datastore では区別されません。それは、モデルの全ての属性に(null かもしれませんが)値があるからです。 null を許容する型(ビルトインの int や boolean などではない型)の属性に null が入っていたら、モデルが保存されるときにエンティティのプロパティに null が設定されます。 データストアのエンティティがモデルにロードされ、モデルのある属性に対応するプロパティが存在しなくて、その属性が null を入れることのできる単値の型だった場合、その属性には null が入ります。モデルがデータストアに戻されるときには、存在しなかったプロパティには null が設定されてデータストアに保存されます。属性が null 不可の場合に、対応するプロパティがないエンティティを読み込んだ場合は、その属性にはデフォルト値が設定されます。エンティティの生成と再生成に同じモデルを使用している場合、このようなことは起こりません。このようなことが起こるのは、モデルが変更された場合か、エンティティが Slim3 Datastore ではなく low-level API を使用して作られた場合です。 エンティティがモデルのフィールドにないプロパティを持っている場合、そのプロパティはモデルからはアクセスできません。モデルがデータストアに戻された場合は、そのプロパティは削除されます。 キーとエンティティグループSlim3 Datastore を日本語に訳してみた | | http://sites.google.com/site/slim3appengine/slim3-datastore/keys-and-entity-groups データストア内の全エンティティに「キー」があります。キーとはアプリケーションの全エンティティに対してユニークな識別子です。キーにはいくつかの要素があります。
Kind と Name と ID全てのエンティティには特定の kind があります。kind とはテーブルのようなものです。Slim3 Datastore はモデルクラスの単純名を kind 名として使用します。 例えば、このモデルの kind は"Employee"です。 import org.slim3.datastore.Model; @Model public class Employee { ... } @Model(kind = "...") アノテーションを使用して kind 名を指定することができます。 import org.slim3.datastore.Model; @Model(kind = "Emp") public class Employee { ... } キーの ID の部分は、アプリケーションが文字列で指定することも、データストアに数値IDを自動生成してもらうようにすることもできます。 アプリケーションで文字列 ID を生成するためには、Key 型の値を ID で作ってその値をフィールドに設定します。 import com.google.appengine.api.datastore.Key; import org.slim3.datastore.Datastore; // ... Key key = Datastore.createKey(Employee.class, "Alfred.Smith@example.com"); Employee emp = new Employee(); emp.setKey(key); ... Datastore.put(emp); システムで設定される数値IDを使う場合は、キーのフィールドを null のままにしておきます。そうすると、キーのフィールドは Datastore.put() メソッドを使用してデータストアに書き込まれる際に設定されます。 import com.google.appengine.api.datastore.Key; import org.slim3.datastore.Datastore; // ... Employee e = new Employee(); ... Datastore.put(e); システムで設定される数値IDをデータストアに保存する前に取得したい場合は Datastore.allocateId() を使います。 import com.google.appengine.api.datastore.Key; import org.slim3.datastore.Datastore; // ... Key key = Datastore.allocateId(Employee.class); Employee e = new Employee(); e.setKey(key); Datastore.put(e); システムで設定される数値IDをデータストアに保存する前に複数取得したい場合は Datastore.allocateIds() を使います。 import com.google.appengine.api.datastore.Key; import com.google.appengine.api.datastore.KeyRange; import org.slim3.datastore.Datastore; import java.util.ArrayList; import java.util.Iterator; import java.util.List; // ... List<Employee> list = new ArrayList<Employee>(); Iterator<Key> keys = Datastore.allocateIds(Employee.class, 100).iterator(); while (keys.hasNext() { Employee e = new Employee(); e.setKey(keys.next()); ... list.add(e); } Datastore.put(list);
エンティティグループと祖先とパス全てのエンティティは「エンティティグループ」に所属しています。エンティティグループとは、単一のトランザクションで扱うことのできる1つ以上のエンティティのセットです。App Engine はエンティティグループの関連に基づいて、複数のエンティティを分散ネットワークの同じ部分に格納します。トランザクションはエンティティグループに対してデータストアの操作を開始し、全ての操作が実行されるか、または失敗時には全ての操作が実行されないかのどちらかとなります。 アプリケーション指定の文字列IDを使用して子のキーを生成する場合は「親」のキーを次のように指定することができます。 import com.google.appengine.api.datastore.Key; import org.slim3.datastore.Datastore; // ... Key parentKey = ...; Key childKey = Datastore.createKey(parentKey, Child.class, "..."); 自動生成のIDを使用する場合は「親」のキーを次のように指定することができます。 import com.google.appengine.api.datastore.Key; import org.slim3.datastore.Datastore; // ... Key parentKey = ...; Key childKey = Datastore.allocateId(parentKey, Child.class); 自動生成IDの場合に複数の子のキーを設定する際には「親」のキーを次のように指定することができます。 import com.google.appengine.api.datastore.Key; import org.slim3.datastore.Datastore; import java.util.ArrayList; import java.util.Iterator; import java.util.List; // ... Key parentKey = ...; List<Child> list = new ArrayList<Child>(); Iterator<Key> childKeys = Datastore.allocateIds(parentKey, Child.class, 100).iterator(); while(childKeys.hasNext()) { Child child = new Child(); child.setKey(childKeys.next()); ... list.add(child); } Datastore.put(list); 親を持たないエンティティは「ルート」エンティティとなります。別のエンティティの親であるエンティティも親を持つことができます。あるエンティティからルートまでの親エンティティのチェーンがエンティティの「パス」となります。パスのメンバーはエンティティの「祖先」となります。エンティティの親はエンティティの作成時に定義され、後で変更することはできません。 単一のトランザクションでできるのは
です。 トランザクションについての詳しい情報は、トランザクション を参照してください。 あるエンティティの祖先エンティティが削除されても、子孫エンティティは削除されません。子孫エンティティは完全キーを使用してアクセスすることができます。 エンティティグループを使用する際の Tips :
モデルの作成、取得、削除Slim3 Datastore を日本語に訳してみた | | http://sites.google.com/site/slim3appengine/slim3-datastore/creating-getting-and-deleting-data 単純に Datastore.put() を呼び出せば、モデルをデータストアに保存することができます。 Slim3 Datastore はデータストアのどのエンティティがそのデータオブジェクトと一致するのかを見失わないようにオブジェクトの主キーフィールドを使用し、新しいオブジェクトに対しては自動的にキーを生成することができます。エンティティを素早く取得するためには、キーを使用します。キーは(アカウント ID のような)既知の値から生成することができます。 モデルの作成http://sites.google.com/site/slim3appengine/slim3-datastore/creating-getting-and-deleting-data/put データストアにモデルを保存するには Datastore.put() にインスタンスを渡して呼び出します。 Employee employee = new Employee(); ... Datastore.put(employee); トランザクション外では Datastore.put() の呼び出しは同期的に行われ、オブジェクトが保存されてインデックスが更新されるまで処理は戻りません。 複数のモデルを保存するにはモデルのコレクションか配列を Datastore.put() に渡します。この方が1つずつ呼び出すよりも効率が良いです。 List<Employee> list = new ArrayList<Employee>(); for (int i = 0; i < 100; i++) { Employee emp = new Employee(); ... list.add(emp); } Datastore.put(list); Employee emp = new Employee(); ... Employee emp2 = new Employee(); ... Datastore.put(emp, emp2); キーによるモデルの取得モデルをキーから取得する場合は Datastore.get() メソッドを使用します。このメソッドにはモデルのクラスとキーを渡します。 Key key = ...; Employee emp = Datastore.get(Employee.class, key); 複数のモデルをキーから取得する場合は Datastore.get() にモデルのクラスと複数のキーを渡します。この方が1つずつ呼び出すよりも効率が良いです。 List<Key> keys = ...; List<Employee> list = Datastore.get(Employee.class, keys);
モデルの更新モデルを更新するには、モデルを取得し、変更し、データストアに保存( put )します。 public void updateEmployeeTitle(Key key, String newTitle) { EmployeeMeta e = new EmployeeMeta(); Employee emp = Datastore.get(e, key); emp.setTitle(newTitle); Datastore.put(emp); } 複数のモデルの更新は次のように行います。この方が1つずつ呼び出すよりも効率が良いです。 public void updateEmployeesTitle(List<Key> keys, String newTitle) { EmployeeMeta e = new EmployeeMeta(); List<Employee> list = Datastore.get(e, keys); for (Employee emp : list) { emp.setTitle(newTitle); } Datastore.put(list); } モデルの削除モデルをデータストアから削除する場合は Datastore.delete() にキーを渡します。 Key key = ...; Datastore.delete(key); 複数のモデルを削除するにはキーのコレクションか配列を Datastore.delete() に渡します。この方が1つずつ呼び出すよりも効率が良いです。 List<Key> keys = ...; Datastore.delete(keys);
Datastore.delete(key, key2, key3);
*1: *2:自信ない。A complete key can be represented by the kind and ID or key name of each entity in the path. |
コメントありがとうございます。
なるほど。
「何もしなければ(自動生成がONになっていて)勝手に(自動生成用の)インデックス設定ファイルに候補が追加される。」
ということですね。文の通りなんですね。ありがとうございます。
slim3-blankプロジェクトから.projectや.settingsや.externalToolBuildersを既存プロジェクトにコピーして.apt_generatedというソースフォルダを作成したらMetaデータが自動生成できるようになりました。
どれが必要でどれが不必要だったかはわかりませんが報告まで。
ご報告ありがとうございます。
「slim3-gen-xxx.jar を 注釈処理のファクトリー・パスに追加します。」
の部分がうまく動作できていなかったのかなと思います。設定ファイルでいうと「.factorypath」です。
でも、自動生成できるようになって良かったです。
slim3 について質問や意見などあれば
http://groups.google.co.jp/group/slim3-user-japan
に投稿するとみなさんが答えてくれますよ。
slim3-gen-xxx.jar を 注釈処理のファクトリー・パスから一度削除して、
再度追加し直したら.apt_generatedフォルダに生成されました。