2010-03-03 63 views
4

我想构建一个应用程序,其中由电子邮件地址标识的用户可以拥有多个应用程序帐户。每个帐户可以有一个或多个用户。我正尝试在Google App Engine Java中使用JDO存储功能。这是我的尝试:坚持JDO - 如何使用JDOQL查询集合的属性?

@PersistenceCapable 
@Inheritance(strategy = InheritanceStrategy.NEW_TABLE) 
public class AppAccount { 
    @PrimaryKey 
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) 
    private Long id; 

    @Persistent 
    private String companyName; 

    @Persistent 
    List<Invoices> invoices = new ArrayList<Invoices>(); 

    @Persistent 
    List<AppUser> users = new ArrayList<AppUser>(); 

    // Getter Setters and Other Fields 
} 

@PersistenceCapable 
@EmbeddedOnly 
public class AppUser { 

    @Persistent 
    private String username; 

    @Persistent 
    private String firstName; 

    @Persistent 
    private String lastName; 

    // Getter Setters and Other Fields 
} 

当用户登录时,我想检查他有多少个帐户。如果他或她属于多个人,那么他或她将会看到一个仪表板,他/她可以点击他/她想要加载的账户。这是我的代码来检索他/她注册的应用程序帐户列表。

public static List<AppAccount> getUserAppAccounts(String username) { 
    PersistenceManager pm = JdoUtil.getPm(); 
    Query q = pm.newQuery(AppAccount.class); 
    q.setFilter("users.username == usernameParam"); 
    q.declareParameters("String usernameParam"); 
    return (List<AppAccount>) q.execute(username); 
} 

,但我得到了一个错误:

SELECT FROM invoices.server.AppAccount WHERE users.username == usernameParam PARAMETERS String usernameParam: Encountered a variable expression that isn't part of a join. Maybe you're referencing a non-existent field of an embedded class. 
org.datanucleus.store.appengine.FatalNucleusUserException: SELECT FROM com.softamo.pelicamo.invoices.server.AppAccount WHERE users.username == usernameParam PARAMETERS String usernameParam: Encountered a variable expression that isn't part of a join. Maybe you're referencing a non-existent field of an embedded class. 
    at org.datanucleus.store.appengine.query.DatastoreQuery.getJoinClassMetaData(DatastoreQuery.java:1154) 
    at org.datanucleus.store.appengine.query.DatastoreQuery.addLeftPrimaryExpression(DatastoreQuery.java:1066) 
    at org.datanucleus.store.appengine.query.DatastoreQuery.addExpression(DatastoreQuery.java:846) 
    at org.datanucleus.store.appengine.query.DatastoreQuery.addFilters(DatastoreQuery.java:807) 
    at org.datanucleus.store.appengine.query.DatastoreQuery.performExecute(DatastoreQuery.java:226) 
    at org.datanucleus.store.appengine.query.JDOQLQuery.performExecute(JDOQLQuery.java:85) 
    at org.datanucleus.store.query.Query.executeQuery(Query.java:1489) 
    at org.datanucleus.store.query.Query.executeWithArray(Query.java:1371) 
    at org.datanucleus.jdo.JDOQuery.execute(JDOQuery.java:243) 
    at com.softamo.pelicamo.invoices.server.Store.getUserAppAccounts(Store.java:82) 
    at com.softamo.pelicamo.invoices.test.server.StoreTest.testgetUserAppAccounts(StoreTest.java:39) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) 
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 

任何想法?

我得到的JDO持续性完全错误吗?

回答

5

AppAccount类有一个users变量是ListList直接没有用户名属性。

你需要做这样的事情:

@PersistenceCapable 
@EmbeddedOnly 
public class AppUser { 

    @Persistent 
    private String username; 

    @Persistent 
    private String firstName; 

    @Persistent 
    private String lastName; 

    //override equals method for List .contains 
    @Override 
    public boolean equals(AppUser au) { 
     return au.getUsername().equals(this.username); 
    } 

    // Getter Setters and Other Fields 
} 

Query q = pm.newQuery(AppAccount.class); 
//the : denotes an implicit variable will be passed to query execute method 
q.setFilter("users.contains(:username)"); 
//create a new AppUser with the username you want to check, this query will find the AppAccount with any AppUser with the same username, because the .equals method of AppUser has been overridden to return true based on the username member variable 
List<AppAccount> results = (List<AppAccount>)query.execute(new AppUser(username)); 
+0

这是如何工作的时候没有为类APPUSER没有1参数的构造函数?感谢:) – jmort253 2012-01-16 19:02:26

+0

Google提供[某些文档](https://developers.google.com/appengine/docs/java/datastore/jdo/queries#Filters)用于过滤收集内容。 jmort253:AppUser的构造函数参数无关紧要。重要的是,提供给[query.execute()](http://db.apache.org/jdo/api30/apidocs/javax/jdo/Query#execute())的“username”过滤器参数是equals()给AppUser你希望你的结果AppAccount值在他们的用户集合中。这是Finbarr通过覆盖.equals()方法完成的。 – dmiller309 2013-07-31 23:04:16