2016-04-09 9 views
0

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をデータベースに保存しているようです。何故ですか?

答えて

0

あなたが他のいくつかの問題を抱えているかもしれませんが、ルートの問題があることである:あなたが取引

の内部で定期的にクエリを使用することはできませんトランザクション

  • を使用する必要が

    1. ユーザー名の一意性を強制する場合は、IDがユーザー名である別のユーザー名エンティティを作成し、Userレコードと共にUsernameをロード/作成する必要があります。ユーザー名のロードはプライマリキーで行われるため、トランザクションの一意性が保証されます。

  • 関連する問題