2010-03-03 32 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