我正在使用JDO在Google App Engine中创建一个Java Web应用程序。
我有一个类User,它具有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,然后获取对应的User,例如:
//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,就可以使用其键来检索User,例如:
//... then retrieve the User
user = pm.getObjectById(User.class, tokens.get(0).getKey().getParent());
//return retireved user if any...
通过这种方式,我执行键查找而不是其他查询,但是无论如何,我仍然两次访问数据存储区...
最佳答案
一种可能的解决方案是在两个实体类之间具有双向拥有的一对一关系。那么你就可以:
通过查询令牌获得所需的SessionToken
。
通过调用获取的SessionToken
的适当的getter方法,获取User
的父SessionToken
。
另一种可能的解决方案是遵循“ Google App Engine Java持久性”博客中所述的“执行跨所有关系的简单联接”。