Непоследовательное поведение транзакции в локальном хранилище данных Appengine?

В документации 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.

Имея это в виду, я создал следующие два модульных теста, чтобы проверить это (с локальным хранилищем данных). Я ожидаю, что оба моих теста пройдут ниже. Однако проходит только «test1», а «test2» - нет. Единственная разница - это фиксация tx1 в "test1".

Это ошибка в локальном хранилище данных, неправильное понимание документации 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();
        }
    }
}

person sappenin    schedule 09.03.2012    source источник
comment
Нет commit() в test1?   -  person Peter Knego    schedule 09.03.2012


Ответы (1)


Я подозреваю, что транзакция на самом деле не начинается, когда вы вызываете datastore.beginTransaction - она ​​начинается, когда транзакция впервые попадает в базу данных - это был бы оптимальный способ минимизировать блокировки на стороне базы данных.

В тесте 2 вы можете попробовать добавить дополнительный get () в txn2 перед txn1.commit (). Затем второй get () (где вы сейчас выполняете txn2 get) должен вернуть null.

person dragonx    schedule 09.03.2012
comment
Да, ваши подозрения оправдались. Выполнение get () для второй транзакции перед фиксацией первой, похоже, инициирует фактическую транзакцию в хранилище данных. Я предполагаю, что это поведение идентично фактическому хранилищу данных, но не уверен на 100% в этом. Спасибо за вашу помощь! - person sappenin; 11.03.2012