2012-07-04 107 views
2

考虑一个基于网络的系统,其中多个用户可能同时创建帐户。该系统要求用户具有唯一的用户名以及唯一的电子邮件地址。在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用户那里得到密钥,并将它作为上面代码中查询的祖先密钥。现在,这也没有工作,我仍然得到重复的电子邮件地址。我也尝试过配置交易,所以这是一个跨组交易,但这也没有帮助。

那么,关于如何使这个工作的任何提示?它有可能吗?

回答

相关问题