交易和锁定与Appengine

时间:2012-07-06 19:17:08

标签: google-app-engine objectify

我在下面有一个类似的代码,我试图找出事务锁定:

DAOT.repeatInTransaction(new Transactable() {
        @Override
        public void run(DAOT daot)
        {
                Points points = daot.ofy().find(Points.class, POINTS_ID);
                // do something with points
                takes_a_very_long_time_delay(); // perhaps 10 secs
                daot.ofy().put(points);
        }
});

上面的代码是从Java servlet中执行的。例如,该操作预计工作10秒。在那段时间之间,我有一个测试将调用另一个将删除Points实体的servlet,我期望删除操作失败或至少在上面的事务完成后删除实体。

但是,在上述代码执行期间删除了该实体。在我的实际应用程序中,我添加了异常处理,以在尝试访问或编辑不存在的实体时抛出异常。

从那里开始,应用程序在我执行将删除上面代码中的Entity的servlet之后抛出“Entity not found"异常。

虽然我已经使用了GAE Transactions,但我认为我仍然遗漏了一些原因,这就是我的测试失败的原因。

使用Delete servlet删除事务的代码:

DAOT.repeatInTransaction(new Transactable() {
        @Override
        public void run(DAOT daot)
        {
                Points points = daot.ofy().find(Points.class, POINTS_ID);
                daot.ofy().delete(points);
        }
});

如何确保实体的delete之类的新操作会等到事务期间当前操作在实体上发生?

2 个答案:

答案 0 :(得分:5)

App Engine使用乐观并发,而不是锁定。也就是说,一组实体上的事务不会阻止其他进程在事务运行时修改这些实体。相反,当事务尝试提交时,它将检查在事务执行期间是否进行了任何修改,如果有,则丢弃所有更改并从头开始再次运行您的函数。

答案 1 :(得分:1)

我假设您使用objectify来处理数据存储区。 首先,您需要确保daot.ofy()使用显式事务集(ObjectifyFactory.beginTransaction())而不是ObjectifyFactory.begin()返回objectify实例。然后确保对find()和delete()调用(以及find()/ put对)使用相同的objectify实例。