通过其子对象中的属性从数据存储区检索对象

时间:2013-03-20 18:04:18

标签: java google-app-engine google-cloud-datastore jdo

我正在使用 JDO Google App Engine 中创建 Java 网络应用。

我有一个用户类,其属性为 SessionToken 。这两个类都是持久的,具有拥有的一对一关系。

@PersistenceCapable
public class User {    
  @PrimaryKey
  @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
  private Key key;
  @Persistent
  private SessionToken sessionToken;    
  //getters and setters...
}

@PersistenceCapable
public class SessionToken { 
  @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
  private Key key;
  @Persistent
  private String token;    
  //getters and setters...
}

现在,我希望有一种方法可以使用SessionToken的属性标记从数据存储区获取用户。我的意思是,我需要这样的东西:

Query query = pm.newQuery(User.class);
query.setFilter("sessionToken.token == tokenParam");
query.declareParameters("String tokenParam");
//return retrieved user if any...

但这不起作用,因为查询无法访问子对象中的属性。

它引发了这个异常:

javax.jdo.JDOFatalUserException: SELECT FROM com.mockgaeapp.User 
WHERE sessionToken.token == tokenParam PARAMETERS String tokenParam: 
Can only reference properties of a sub-object if the sub-object is embedded.

我能做到的唯一方法是首先获得SessionToken,然后是相应的用户,例如:

//First retrieve the SessionToken...
Query query = pm.newQuery(SessionToken.class);
query.setFilter("token == tokenParam");
query.declareParameters("String tokenParam");
List<SessionToken> tokens = (List<SessionToken>) query.execute(sessionToken);
if (!tokens.isEmpty()) {

  //... then retrieve the User
  query = pm.newQuery(User.class);
  query.setFilter("sessionToken == sessionTokenParam");
  query.declareParameters("String sessionTokenParam");
  List<User> users = (List<User>) query.execute(tokens.get(0));
  //return retireved user if any...
}

我想知道是否有其他方法可以做到这一点,只使用一个查询,或者即使还有其他方法......此外我们必须考虑到这个操作将被执行多次......

编辑:我发现了一种更简单的方法。一旦我像上一个例子中那样检索了SessionToken,我就会使用它的密钥来检索用户,如:

//... then retrieve the User
user = pm.getObjectById(User.class, tokens.get(0).getKey().getParent());
//return retireved user if any...

这样我会进行密钥查找而不是其他查询,但无论如何我仍然访问数据存储区两次......

2 个答案:

答案 0 :(得分:1)

一种可能的解决方案是在两个实体类之间建立双向拥有的一对一关系。然后你可以:

  1. 通过查询令牌获取所需的SessionToken
  2. 通过调用获得的SessionToken的相应getter方法获取User的父SessionToken
  3. 另一种可能的解决方案是遵循“Google App Engine Java Persistence”博客中的“执行简单加入跨越所有关系”。

答案 1 :(得分:0)

Query query = pm.newQuery(User.class);
query.setFilter("sessionToken == tokenParam && tokenParam == 'my_token'");
query.declareParameters(SessionToken.class.getName() + " tokenParam");

应该有效