如何使用Objectify for AppEngine app拒绝并发重复保存

时间:2014-01-30 09:51:49

标签: google-app-engine objectify

我们有一个定义为(id, name, school, & OTHER-FIELDS)的实体。 id由数据存储区自动分配。 我们希望确保<name, school>的组合在数据存储区中是唯一的。

我们的代码写得像这样:

/* First check uniqueness, then save */
public void savePerson(final Person newPerson) {
    List<Person> existing = ofy().load().type(Person.clas)
            .filter("name=", name)
            .filter("school=", school)
            .list();
    if (existing == null || existing.isEmpty()) {
        ofy.transact(new VoidWork() {
            @Override
            public void vrun() {
                ofy.save.entity(newPerson).now();
            }
        }
    }
}

但是如果同时发生多个相同的savePerson调用仍然会发生(不可避免地我们会遇到这种情况),重复检查将失败(我认为因为当他们开始调用savePerson()时数据实际上没有保存) ,我们在AppEngine数据存储区中找到了最终具有相同<name, school>组合的重复实体。

我们确实希望在我们的数据存储中确保<name, school&gt;我们最终将拥有一个独特的实体 有人可以教我如何添加重复检查原子吗?如果我将现有的实体检查代码移动到交易上下文中会有帮助吗?

例如,以下代码是否有效?

/* Put filtering search into transaction too */
public void savePerson(final Person newPerson) {
    ofy.transact(new VoidWork() {
        @Override
        public void vrun() {
            List<Person> existing = ofy().load().type(Person.class)
                    .filter("name=", name)
                    .filter("school=", school)
                    .list();
            if (existing == null || existing.isEmpty()) {
                ofy.save.entity(newPerson).now();
            }
        }
    }
}

如果我应该提供更多细节,请告诉我。

1 个答案:

答案 0 :(得分:0)

为了做你想做的事情,如果已经有给定名字+学校并保存实体,则必须使用单一交易来阅读;否则,如果您有许多并发用户,您将结束重复。您可以只加载第一个实体,而不是加载整个列表[即第一()]。确保&#39; name&#39;和学校&#39;被索引(即@Index)。另请检查您是否在web.xml中有ObjectifyFilter。

但是请注意,同一所学校可能有两个同名的人,所以你应该添加另一种方法来区分人。