3

複数のユーザーが同時にアカウントを作成する Web ベースのシステムを考えてみましょう。システムでは、ユーザーが一意のユーザー名と一意の電子メール アドレスを持っている必要があります。RDBMS では、これは単純です。「email」フィールドは UNIQUE としてマークされます。これにデータストアの方法でどのようにアプローチできますか?

これは私の最初の試みでした:

// Create entity using the username as key
String username = ... // provided by the user
String email = ...    // provided by the user
Entity entity = new Entity("Users", KeyFactory.createKey("User", username));
entity.setProperty("email", email);

// Create a query that matches the email property
Query q = new Query();
q.setFilter(new FilterPredicate("email", FilterOperator.EQUAL, email));

// Start a transaction
Transaction txn = datastore.beginTransaction();

try {
    // Try to get an entity with that username
    datastore.get(KeyFactory.createKey("User", username);
}
catch(EntityNotFoundException e) {
    // No entity with that username, make sure the e-mail
    // is not taken either
    PreparedQuery pq = datastore.prepare(q);
    if (pq.countEntities(FetchOptions.Builder.withLimit(1)) == 0) {
        // The e-mail isn't taken either, all good
        datastore.put(entity);
        txn.commit();

        ... handle success here ...

        return;
    }
}
finally {
    if (txn.isActive())
        txn.rollback();
}

... handle failure here ...

しかし、いくつかの簡単なテストの後、クエリが少し前に行われた「プット」を常に「見る」とは限らないことに気付きました (結果整合性、推測する必要がありました)。これを回避するために、そのクエリを「ダミー」の祖先クエリに変えてみました。

したがって、この「ダミー」祖先クエリは次のように機能します。名前付きキーを使用して、種類 RootUser のエンティティを作成します。この root ユーザーからキーを取得し、それを上記のコードのクエリの祖先キーにします。それもうまくいきませんでした。今でも重複した電子メール アドレスを取得しています。また、グループ間トランザクションになるようにトランザクションを構成しようとしましたが、それも役に立ちませんでした。

それで、これを機能させる方法に関するヒントはありますか?それはまったく可能ですか?

4

1 に答える 1

2

クイックバージョン:別のエンティティ「種類」を使用し、この種類のオブジェクトのIDとして一意の値を保存する必要があります。例えば。「User.username:myusername」、「User.email:email@example.com」。これらのエントリを最初に作成することで、値が一意でない場合を知ることができます。

実装例については、こちらを ご覧ください。http://webapp-improved.appspot.com/_modules/webapp2_extras/appengine/auth/models.html#Unique

于 2012-07-05T02:43:32.497 に答える