数据存储文档说:
为实体组提交事务后,App Engine 会再次检查事务中使用的实体组的上次更新时间。如果它在我们的初始检查后发生了变化,App Engine 会抛出一个异常
new Entity("TestEntity",1)
我有三个关于在两个并发事务中执行事务数据存储放置的测试用例。
test1:将实体放在第一个事务中,将实体放在第二个事务中,并提交两个事务。该测试在开发服务器和独立单元测试中运行时通过(即抛出
ConcurrentModificationException
),但在生产服务器中运行时失败(即在不抛出异常的情况下执行)。test2:将实体放在第一个事务中并提交,然后将实体放在第二个事务中并提交。这个测试总是失败。
test3:尝试在两个事务中获取(不存在的)实体,然后执行 test2。这个测试总是通过 throw
ConcurrentModificationException
。
从这些测试中,我得出结论,既不beginTransaction
也不put
保证执行“初始检查”,我需要支付一笔费用以保证交易的完整性。那是对的吗?
@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();
}