我有2台Android设备连接的App Engine应用程序(Java)。 App Engine后端提供了一个“setUsername”函数,允许客户端设置用户名。
public void setUsername(@Named("username") String username, User oauthUser) throws OAuthRequestException, BadRequestException {
UserRecord user = OAuthTools.getUser(oauthUser);
updateUsername(user, username);
ofy().save().entity(user);
}
private void updateUsername(UserRecord user, String username) throws BadRequestException {
user.name = username;
//Search for a user that already has the desired username. Note that the entity is NOT being saved in this method.
UserRecord existingUser = ofy().load().type(UserRecord.class).filter("normalizedName", user.normalizedName).first().now();
if(existingUser != null && existingUser.id != user.id) throw new BadRequestException("username taken");
}
问题如下: 在我通过调用setUsername(例如,'aaaa')为第一个Android客户端设置了一些用户名后,我尝试使用第二个Android客户端设置相同的用户名(不同时,在两次调用之间至少间隔10秒)。后端然后正确地抛出BadRequestException并显示消息“username taken”,但它仍然将相同的用户名写入数据库中的第二个用户,即两个用户在第二个客户端的此调用之后设置了用户名'aaaa'。
为什么会这样?我的理解是,在抛出Exception时代码执行应该已经停止,因此永远不应该调用ofy()。save()调用。
本地应用引擎开发服务器以及后端应用程序部署到Google服务器时都会出现问题。
编辑:问题似乎是objectify将updateUsername中创建的UserRecord保存到数据库,尽管ofy()。save()永远不会被调用。为什么?
答案 0 :(得分:0)
您可能还有其他几个问题,但根本问题是:
如果要强制实施用户名的唯一性,则需要创建一个单独的用户名实体,其id为用户名本身,并加载/创建用户名以及用户记录。因为您的用户名加载是主键,所以您可以在事务上保证其唯一性。