是否会使用此端点将两个实体写入数据存储区?

时间:2017-05-05 03:16:19

标签: google-app-engine objectify

我有一个端点方法,它首先使用查询来查看是否存在具有某些参数的实体,如果不存在,则会创建它。如果它存在,我想在变量中增加一个计数器:

Report report = ofy().load().type(Report.class)
    .filter("userID", userID)
    .filter("state", state).first().now();

if (report == null) { 
    //write new entity to datastore with userID and state
} else {
    //increase counter in entity +1
    report.setCount(report.count+1)
    //save entity to datastore
}

我的问题是,如果有人点击按钮以非常快速的方式执行具有相同参数的上述端点,会发生什么?是否会将两个相同的报表实体写入数据存储区?我只想确保写一个。

1 个答案:

答案 0 :(得分:1)

这个代码本身并不安全,并且具有允许创建多个报告的竞争条件。

为了确保安全,您需要在事务中运行代码。这意味着您必须具有祖先查询(或将其转换为简单的主键查找)。一种选择是向报告提供用户的@Parent。那么你可以这样:

ofy().transact(() -> {
    Report report = ofy().load().type(Report.class)
        .ancestor(user)
        .filter("state", state).first().now();

    if (report == null) { 
        //write new entity to datastore with userID and state
    } else {
        //increase counter in entity +1
        report.setCount(report.count+1)
        //save entity to datastore
    }
});