2つのAndroidデバイスが接続するApp Engineアプリケーション(Java)があります。 App Engineのバックエンドには、クライアントがユーザ名を設定できるようにする関数 'setUsername'が用意されています。App EngineはBadRequestExceptionをスローしてもプログラムの実行を続行します
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クライアントといくつかのユーザ名を設定した後、私は2番目のAndroidのクライアントを使用して、同じユーザー名を設定しよう(ではありません同時に、通話の間に少なくとも10秒が経過した)。バックエンドは「username taken」というメッセージとともにBadRequestExceptionを正しくスローしますが、データベース内の2番目のユーザーには同じユーザー名を書き込みます。つまり、2番目のクライアントからこの呼び出しの後に両方のユーザーにユーザー名 'aaaa'が設定されます。
どうしてですか? Exceptionを投げるときにコード実行が止まっていなければならないので、ofy()。save()コールは決して呼び出されてはいけません。
この問題は、ローカルアプリケーションエンジン開発サーバーと、バックエンドアプリケーションがGoogleサーバーに展開されたときの両方で発生します。
編集:オブジェクト化は、ofy()。save()が呼び出されることはありませんが、オブジェクト化によってupdateUsernameで作成されたUserRecordをデータベースに保存しているようです。何故ですか?