4

AppEngineのドキュメントがデータストアのトランザクションについてはこれを言う:念頭に置いて http://code.google.com/appengine/docs/java/datastore/transactions.html#Isolation_and_ConsistencyAppengine Local Datastoreでのトランザクションの動作が一貫していませんか?

In a transaction, all reads reflect the current, consistent state of the 
Datastore at the time the transaction started. This does not include 
previous puts and deletes inside the transaction. Queries and gets inside 
a transaction are guaranteed to see a single, consistent snapshot of the 
Datastore as of the beginning of the transaction. 

、私は(ローカルデータストアに対して)これをテストするには、以下の2つのユニットテストを作成しました。私は以下の両方のテストが合格すると期待しています。ただし、「test1」のみが通過し、「test2」は失敗します。唯一の違いは、 "test1"のtx1のコミットです。

ローカルデータストアのバグか、GAEドキュメントの誤解か、単体テストのバグですか?または、他の何か?

ありがとうございます!

@Test(expected = EntityNotFoundException.class) 
public void test1() throws EntityNotFoundException { 
    DatastoreService datastore = DatastoreServiceFactory.getDatastoreService(); 

    // Create 2 Transactions... 
    Transaction txn1 = datastore.beginTransaction(); 
    Transaction txn2 = datastore.beginTransaction(); 

    try { 
     Key entityWithStringKey = KeyFactory.createKey("TestEntity", "test"); 
     Entity entityWithString = new Entity(entityWithStringKey); 
     datastore.put(txn1, entityWithString); 

     entityWithString = datastore.get(txn2, entityWithStringKey); 
     // The above should throw EntityNotFoundException 
     assertNull(entityWithString); 
    } 
    finally { 
     if (txn1.isActive()) { 
     txn1.rollback(); 
    } 

    if (txn2.isActive()) { 
      txn2.rollback(); 
    } 
} 


@Test(expected = EntityNotFoundException.class) 
public void test2() throws EntityNotFoundException { 
    DatastoreService datastore = DatastoreServiceFactory.getDatastoreService(); 

    // Create 2 Transactions... 
    Transaction txn1 = datastore.beginTransaction(); 
    Transaction txn2 = datastore.beginTransaction(); 

    Key entityWithStringKey = KeyFactory.createKey("TestEntity", "test"); 

    try { 
     Entity entityWithString = new Entity(entityWithStringKey); 
     datastore.put(txn1, entityWithString); 
     txn1.commit(); 
    } finally { 

    if (txn1.isActive()) { 
     txn1.rollback(); 
    } 
    } 

    try { 
     Entity entityWithString = datastore.get(txn2, entityWithStringKey); 
     assertNull(entityWithString); 
     // The above should throw EntityNotFoundException 
    } 
    finally { 
     if (txn2.isActive()) { 
      txn2.rollback(); 
     } 
    } 
} 
+0

'test1'に' commit() 'はありませんか? –

答えて

4

私はあなたがdatastore.beginTransactionを呼び出すときと、トランザクションが実際に始まっていない疑いがある - データベース側でロックを最小化するための最適な方法だろう - トランザクションデータベースを最初に当たったとき、それが開始されます。

テスト2では、txn1.commit()の前にtxn2に追加のget()を入れてみることができます。次に、2番目のget()(現在txn2 getを実行しているところ)はnullを返す必要があります。

+0

はい、あなたの疑惑は正しいです。最初のトランザクションをコミットする前に2番目のトランザクションでget()を実行すると、データストア内の実際のトランザクションが開始されるようです。私はこの振る舞いが実際のDatastore上では同じだと推測していますが、100%確実ではありません。ご協力いただきありがとうございます! – sappenin

関連する問題