4

Appengine のドキュメントでは、データストア内のトランザクションについて次のように述べられています: http://code.google.com/appengine/docs/java/datastore/transactions.html#Isolation_and_Consistency

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();
        }
    }
}
4

1 に答える 1

4

datastore.beginTransaction を呼び出したときにトランザクションが実際に開始されないのではないかと思います-トランザクションが最初にデータベースにヒットしたときに開始します-これは、データベース側のロックを最小限に抑えるための最適な方法です。

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

于 2012-03-09T16:04:30.693 に答える