Appengine本地数据存储中的事务行为不一致?

时间:2012-03-09 05:26:57

标签: java google-app-engine google-cloud-datastore localserver

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”失败。唯一的区别是在“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();
        }
    }
}

1 个答案:

答案 0 :(得分:4)

我怀疑当你调用datastore.beginTransaction时事务并没有实际开始 - 它在事务首次命中数据库时开始 - 这将是最小化数据库端锁定的最佳方法。

在测试2中,您可以尝试在txn1.commit()之前在txn2上添加一个额外的get()。然后第二个get()(你当前执行txn2 get)应该返回null。