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

Java 通过子对象中的属性从数据存储中检索对象,java,google-app-engine,google-cloud-datastore,jdo,Java,Google App Engine,Google Cloud Datastore,Jdo,我正在用JDO在googleappengine中创建一个Javaweb应用程序 我有一个类User,它有一个属性SessionToken。这两个类都是持久的,具有一对一的关系 @PersistenceCapable public class User { @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Key key; @Persistent private S

我正在用JDOgoogleappengine中创建一个Javaweb应用程序

我有一个类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,然后获取相应的用户,比如:

//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
  • 通过调用所获得的
    SessionToken
    的相应getter方法,获取
    SessionToken
    的父用户
    User

  • 另一个可能的解决方案是遵循“Google App Engine Java Persistence”博客中所述的“跨所属关系执行简单联接”。

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

  • 通过查询令牌获取所需的
    SessionToken
  • 通过调用所获得的
    SessionToken
    的相应getter方法,获取
    SessionToken
    的父用户
    User
  • 另一个可能的解决方案是遵循“GoogleAppEngineJavaPersistence”博客中的“跨所有关系执行简单连接”

    应该有用


    应该可以工作

    ,但这不起作用,因为查询无法访问子对象中的属性。
    ,除非您明确使用您面临的问题,否则我们无法帮助您。什么样的消息表明无法访问子属性?你是对的,我添加了一个异常,它通过一个完整的堆栈将更具洞察力。但是因为这是我第一次看到这样的异常,我并不是说我已经看到了所有异常,但是我猜这个限制是由
    GAE
    而不是
    Datanucleus
    JDO
    实施的,但是这不起作用,因为查询无法访问子对象中的属性。
    ,我们无法帮助您,除非您明确使用您面临的问题。什么样的消息表明无法访问子属性?你是对的,我添加了一个异常,它通过一个完整的堆栈将更具洞察力。但是因为这是我第一次看到这样的异常,我并不是说我已经看到了所有的异常,但是我想这个限制是由
    GAE
    而不是
    Datanucleus
    JDO
    强制执行的。
    //... then retrieve the User
    user = pm.getObjectById(User.class, tokens.get(0).getKey().getParent());
    //return retireved user if any...
    
    Query query = pm.newQuery(User.class);
    query.setFilter("sessionToken == tokenParam && tokenParam == 'my_token'");
    query.declareParameters(SessionToken.class.getName() + " tokenParam");