Datastoreに格納されたEntityの更新について – おきらく日記

Datastoreに格納されたEntityの更新について、興味深い記事を発見。

MyModelMeta meta = MyModelMeta.get();
MyModel model = Datastore.query(meta)
.filter(meta.field.equal("value"))
.asSingle();
if(model != null) {
model.setField("newValue");
Datastore.put(model);
}

これは、ダメだという事。どうするかというと、Keyでgetして、値を変えて、putする。

MyModel model = Datastore.get(MyModel.class, key.get());
model.setField("newValue");
Datastore.put(model);

queryで取得したEntityをなぜputしていけないのか、なかなか分からなかった。「検索して取得したものと実際に格納されてるものって別だもの」ってどういう事・・?

調べたところ、トランザクション内でqueryは使えないんじゃないかという結果にたどり着いた。

トランザクション – Google App Engine – Google Code

アプリケーションは、トランザクション実行中にクエリを実行できません。しかし、トランザクション中にキーを使用してデータストア エンティティを取得することは可能です。このとき、フェッチされたエンティティは他のトランザクションの内容と一致していることを保証します。トランザクション実行前にキーを準備するか、キー名または ID を使用してトランザクション内にキーを構築できます。

appengine java night #3に行ってきた。 #appengine #ajn3 – あおうさ@日記

transaction 開始後最初のget/putで そのときのタイムスタンプをどこかに取っておく.

commit のときに取っておいたタイムスタンプと同じかどうかを比較する.

ancestor query 以外のqueryではtransactionがかからない.keyに対するgetだとだいtransactionになる.

queryは本来複数の行を相手にしているので,そもそもどのentityグループにぞくしたqueryなのか定義できないから.

ancestor queryは entity groupに対するqueryなので,定義できるから.

Entityを更新する時は、keyでgetしてputする!