データストアのドキュメントには次のように書かれています。
エンティティグループのトランザクションをコミットすると、AppEngineはトランザクションで使用されたエンティティグループの最終更新時刻を再度確認します。最初のチェック以降に変更された場合、AppEngineは例外をスローします
new Entity("TestEntity",1)
2つの同時トランザクションでのトランザクションデータストアプットの実行に関する3つのテストケースがあります。
test1:エンティティを最初のトランザクションに入れ、エンティティを2番目のトランザクションに入れ、両方のトランザクションをコミットします。このテストは
ConcurrentModificationException
、開発サーバーおよびスタンドアロンの単体テストで実行すると合格(つまり、スロー)しますが、本番サーバーで実行すると失敗(つまり、例外をスローせずに実行)します。test2:エンティティを最初のトランザクションに入れてコミットしてから、エンティティを2番目のトランザクションに入れてコミットします。このテストは常に失敗します。
test3:両方のトランザクションで(存在しない)エンティティの取得を試みてから、test2を実行します。このテストは常に。を投げることで合格し
ConcurrentModificationException
ます。
これらのテストから、「初期チェックbeginTransaction
」が実行されることもput
保証もされていないと結論付け、トランザクションの整合性を保証するためにgetを支払う必要があります。あれは正しいですか?
@Test(expected=ConcurrentModificationException.class)
//put1 put2 commit1 commit2
public void test1() {
DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
Transaction txn1 = ds.beginTransaction();
Transaction txn2 = ds.beginTransaction();
ds.put(txn1,new Entity("TestEntity",1));
ds.put(txn2,new Entity("TestEntity",1));
txn1.commit();
txn2.commit();
}
@Test(expected=ConcurrentModificationException.class)
//put1 commit1 put2 commit2
public void test2() {
DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
Transaction txn1 = ds.beginTransaction();
Transaction txn2 = ds.beginTransaction();
ds.put(txn1,new Entity("TestEntity",1));
txn1.commit();
ds.put(txn2,new Entity("TestEntity",1));
txn2.commit();
}
@Test(expected=ConcurrentModificationException.class)
//get1 get2 put1 commit1 put2 commit2
public void test3() throws InterruptedException, ExecutionException {
DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
ds.delete(KeyFactory.createKey("TestEntity", 1));
Transaction txn1 = ds.beginTransaction();
Transaction txn2 = ds.beginTransaction();
Assert.assertNull(getTestEntity(ds, txn1));
Assert.assertNull(getTestEntity(ds, txn2));
ds.put(txn1,new Entity("TestEntity",1));
txn1.commit();
ds.put(txn2,new Entity("TestEntity",1));
txn2.commit();
}