2009-09-04 55 views
0

我嘗試使用JPA在谷歌應用程序引擎(GAE)上對grails應用程序進行一對多單向映射測試。我嘗試定義的一對多單向映射位於User和Role類之間。不幸的是,我被卡住了。只是好奇,是否有任何開發者能夠讓它成功運行。如何爲GAE上的grails應用程序設置一對多單向映射?

以下是我的開發環境:

  • Windows XP專業版
  • 的App Engine SDK 1.2.2
  • Grails的使用1.1.1
  • 插件:應用程序引擎0.8.3,gorm- JPA 0.5

的源代碼位於:

完全錯誤的堆棧跟蹤信息是在這裏:

[java] Sep 4, 2009 2:08:42 AM com.google.apphosting.utils.jetty.JettyLogger warn 
[java] WARNING: Failed startup of context [email protected]75b{/,C:\Documents and Settings\limcheekin\.grails\1.1.1\projects\one2many\stage} 
[java] org.springframework.beans.factory.access.BootstrapException: Error executing bootstraps; nested exception is org.codehaus.groovy.runtime.InvokerInvocationException: org.springframework.orm.jpa.JpaSystemException: Class "com.vobject.grailsfuse.User" has collection field "roles" and this has no mapping in the table for the element class "com.vobject.grailsfuse.Role"; nested exception is javax.persistence.PersistenceException: Class "com.vobject.grailsfuse.User" has collection field "roles" and this has no mapping in the table for the element class "com.vobject.grailsfuse.Role" 
[java]  at org.codehaus.groovy.grails.web.context.GrailsContextLoader.createWebApplicationContext(GrailsContextLoader.java:74) 
[java]  at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:199) 
[java]  at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:45) 
[java]  at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:530) 
[java]  at org.mortbay.jetty.servlet.Context.startContext(Context.java:135) 
[java]  at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1218) 
[java]  at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:500) 
[java]  at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:448) 
[java]  at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40) 
[java]  at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:117) 
[java]  at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40) 
[java]  at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:117) 
[java]  at org.mortbay.jetty.Server.doStart(Server.java:217) 
[java]  at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40) 
[java]  at com.google.appengine.tools.development.JettyContainerService.startContainer(JettyContainerService.java:152) 
[java]  at com.google.appengine.tools.development.AbstractContainerService.startup(AbstractContainerService.java:116) 
[java]  at com.google.appengine.tools.development.DevAppServerImpl.start(DevAppServerImpl.java:218) 
[java]  at com.google.appengine.tools.development.DevAppServerMain$StartAction.apply(DevAppServerMain.java:162) 
[java]  at com.google.appengine.tools.util.Parser$ParseResult.applyArgs(Parser.java:48) 
[java]  at com.google.appengine.tools.development.DevAppServerMain.<init>(DevAppServerMain.java:113) 
[java]  at com.google.appengine.tools.development.DevAppServerMain.main(DevAppServerMain.java:89) 
[java] Caused by: org.codehaus.groovy.runtime.InvokerInvocationException: org.springframework.orm.jpa.JpaSystemException: Class "com.vobject.grailsfuse.User" has collection field "roles" and this has no mapping in the table for the element class "com.vobject.grailsfuse.Role"; nested exception is javax.persistence. PersistenceException: Class "com.vobject.grailsfuse.User" has collection field "roles" and this has no mapping in the table for the element class "com.vobject.grailsfuse.Role" 
[java]  ... 7 more 
[java] Caused by: org.springframework.orm.jpa.JpaSystemException: Class "com.vobject.grailsfuse.User" has collection field "roles" and this has no mapping in the table for the element class "com.vobject.grailsfuse.Role"; nested exception is javax.persistence.PersistenceException: Class "com.vobject.grailsfuse.User" has collection field "roles" and this has no mapping in the table for the element class "com.vobject.grailsfuse.Role" 
[java]  at org.grails.jpa.JpaPluginSupport$__clinit__closure3_closure6_closure11_closure38.doCall(JpaPluginSupport.groovy:452) 
[java]  at BootStrap$_closure1.doCall(BootStrap.groovy:13) 
[java]  ... 7 more 
[java] Caused by: javax.persistence.PersistenceException: Class "com.vobject.grailsfuse.User" has collection field "roles" and this has no mapping in the table for the element class "com.vobject.grailsfuse.Role" 
[java]  at org.datanucleus.jpa.NucleusJPAHelper.getJPAExceptionForNucleusException(NucleusJPAHelper.java:264) 
[java]  at org.datanucleus.jpa.EntityTransactionImpl.commit(EntityTransactionImpl.java:122) 
[java]  ... 9 more 
[java] Caused by: org.datanucleus.exceptions.NucleusUserException: Class "com.vobject.grailsfuse.User" has collection field "roles" and this has no mapping in the table for the element class "com.vobject.grailsfuse.Role" 
[java]  at org.datanucleus.store.mapped.scostore.FKSetStore.<init>(FKSetStore.java:184) 
[java]  at org.datanucleus.store.appengine.DatastoreFKSetStore.<init>(DatastoreFKSetStore.java:38) 
[java]  at org.datanucleus.store.appengine.DatastoreManager.newFKSetStore(DatastoreManager.java:353) 
[java]  at org.datanucleus.store.mapped.MappedStoreManager.getBackingStoreForCollection(MappedStoreManager.java:734) 
[java]  at org.datanucleus.store.mapped.MappedStoreManager.getBackingStoreForField(MappedStoreManager.java:646) 
[java]  at org.datanucleus.sco.backed.HashSet.<init>(HashSet.java:102) 
[java]  at org.datanucleus.util.ClassUtils.newInstance(ClassUtils.java:94) 
[java]  at org.datanucleus.sco.SCOUtils.newSCOInstance(SCOUtils.java:164) 
[java]  at org.datanucleus.state.JDOStateManagerImpl.wrapSCOField(JDOStateManagerImpl.java:3040) 
[java]  at org.datanucleus.store.fieldmanager.LoadFieldManager.internalFetchObjectField(LoadFieldManager.java:92) 
[java]  at org.datanucleus.store.fieldmanager.AbstractFetchFieldManager.fetchObjectField(AbstractFetchFieldManager.java:104) 
[java]  at org.datanucleus.state.AbstractStateManager.replacingObjectField(AbstractStateManager.java:1197) 
[java]  at com.vobject.grailsfuse.User.jdoReplaceField(User.groovy) 
[java]  at com.vobject.grailsfuse.User.jdoReplaceFields(User.groovy) 
[java]  at org.datanucleus.state.JDOStateManagerImpl.replaceFields(JDOStateManagerImpl.java:2772) 
[java]  at org.datanucleus.state.JDOStateManagerImpl.replaceFields(JDOStateManagerImpl.java:2791) 
[java]  at org.datanucleus.state.JDOStateManagerImpl.loadFieldsInFetchPlan(JDOStateManagerImpl.java:1610) 
[java]  at org.datanucleus.ObjectManagerImpl.performDetachAllOnCommitPreparation(ObjectManagerImpl.java:3192) 
[java]  at org.datanucleus.ObjectManagerImpl.preCommit(ObjectManagerImpl.java:2931) 
[java]  at org.datanucleus.TransactionImpl.internalPreCommit(TransactionImpl.java:369) 
[java]  at org.datanucleus.TransactionImpl.commit(TransactionImpl.java:256) 
[java]  at org.datanucleus.jpa.EntityTransactionImpl.commit(EntityTransactionImpl.java:104) 
[java]  ... 9 more 
[java] Sep 4, 2009 2:08:42 AM com.google.apphosting.utils.jetty.JettyLogger warn 
[java] WARNING: Nested in org.springframework.beans.factory.access.BootstrapException: Error executing bootstraps; nested exception is org.codehaus.groovy.runtime.InvokerInvocationException: org.springframework.orm.jpa.JpaSystemException: Class "com.vobject.grailsfuse.User" has collection field "roles" and this has no mapping in the table for the element class "com.vobject.grailsfuse.Role"; nested exception is javax.persistence.PersistenceException: Class "com.vobject.grailsfuse.User" has collection field "roles" and this has no mapping in the table for the element class "com.vobject.grailsfuse.Role": 
[java] Class "com.vobject.grailsfuse.User" has collection field "roles" and this has no mapping in the table for the element class "com.vobject.grailsfuse.Role" 
[java] org.datanucleus.exceptions.NucleusUserException: Class "com.vobject.grailsfuse.User" has collection field "roles" and this has no mapping in the table for the element class "com.vobject.grailsfuse.Role" 
[java]  at org.datanucleus.store.mapped.scostore.FKSetStore.<init>(FKSetStore.java:184) 
[java]  at org.datanucleus.store.appengine.DatastoreFKSetStore.<init>(DatastoreFKSetStore.java:38) 
[java]  at org.datanucleus.store.appengine.DatastoreManager.newFKSetStore(DatastoreManager.java:353) 
[java]  at org.datanucleus.store.mapped.MappedStoreManager.getBackingStoreForCollection(MappedStoreManager.java:734) 
[java]  at org.datanucleus.store.mapped.MappedStoreManager.getBackingStoreForField(MappedStoreManager.java:646) 
[java]  at org.datanucleus.sco.backed.HashSet.<init>(HashSet.java:102) 
[java]  at org.datanucleus.util.ClassUtils.newInstance(ClassUtils.java:94) 
[java]  at org.datanucleus.sco.SCOUtils.newSCOInstance(SCOUtils.java:164) 
[java]  at org.datanucleus.state.JDOStateManagerImpl.wrapSCOField(JDOStateManagerImpl.java:3040) 
[java]  at org.datanucleus.store.fieldmanager.LoadFieldManager.internalFetchObjectField(LoadFieldManager.java:92) 
[java]  at org.datanucleus.store.fieldmanager.AbstractFetchFieldManager.fetchObjectField(AbstractFetchFieldManager.java:104) 
[java]  at org.datanucleus.state.AbstractStateManager.replacingObjectField(AbstractStateManager.java:1197) 
[java]  at com.vobject.grailsfuse.User.jdoReplaceField(User.groovy) 
[java]  at com.vobject.grailsfuse.User.jdoReplaceFields(User.groovy) 
[java]  at org.datanucleus.state.JDOStateManagerImpl.replaceFields(JDOStateManagerImpl.java:2772) 
[java]  at org.datanucleus.state.JDOStateManagerImpl.replaceFields(JDOStateManagerImpl.java:2791) 
[java]  at org.datanucleus.state.JDOStateManagerImpl.loadFieldsInFetchPlan(JDOStateManagerImpl.java:1610) 
[java]  at org.datanucleus.ObjectManagerImpl.performDetachAllOnCommitPreparation(ObjectManagerImpl.java:3192) 
[java]  at org.datanucleus.ObjectManagerImpl.preCommit(ObjectManagerImpl.java:2931) 
[java]  at org.datanucleus.TransactionImpl.internalPreCommit(TransactionImpl.java:369) 
[java]  at org.datanucleus.TransactionImpl.commit(TransactionImpl.java:256) 
[java]  at org.datanucleus.jpa.EntityTransactionImpl.commit(EntityTransactionImpl.java:104) 
[java]  at org.grails.jpa.JpaPluginSupport$__clinit__closure3_closure6_closure11_closure38.doCall(JpaPluginSupport.groovy:452) 
[java]  at BootStrap$_closure1.doCall(BootStrap.groovy:13) 
[java]  at com.google.appengine.tools.development.JettyContainerService.startContainer(JettyContainerService.java:152) 
[java]  at com.google.appengine.tools.development.AbstractContainerService.startup(AbstractContainerService.java:116) 
[java]  at com.google.appengine.tools.development.DevAppServerImpl.start(DevAppServerImpl.java:218) 
[java]  at com.google.appengine.tools.development.DevAppServerMain$StartAction.apply(DevAppServerMain.java:162) 
[java]  at com.google.appengine.tools.util.Parser$ParseResult.applyArgs(Parser.java:48) 
[java]  at com.google.appengine.tools.development.DevAppServerMain.<init>(DevAppServerMain.java:113) 
[java]  at com.google.appengine.tools.development.DevAppServerMain.main(DevAppServerMain.java:89) 

請指點。看看你是否有任何想法出了什麼問題...

謝謝。

回答

0

看起來問題是您沒有角色上的用戶,因爲您需要指定我認爲的集合上的mappedBy。

@OneToMany(mappedBy="user",fetch=FetchType.EAGER) 
Set<Role> roles 

此外,你並不真的需要連接表的東西,因爲你真的沒有在應用程序引擎中的表工作。實質上,角色將存在於用戶實體下。

希望幫助:)

+0

哦,並記住將用戶字段添加到角色類 – 2009-09-04 04:38:20

+0

感謝您的快速響應和有用的建議。我嘗試與您的建議,請參閱http://www.java2s.com/Code/Java/JPA/OneToManyMappingWithMappedByToremoveMappingTable.htm 但我在訪問角色/列表頁面時遇到以下錯誤。 錯誤原因: org.datanucleus.exceptions.NucleusUserException:字段com.vobject.grailsfuse.Role.user應該能夠提供對其父代的引用,但該實體沒有父代。您是否可能試圖在孩子已被保留後,將com.vobject.grailsfuse.Role的實例建立爲com.vobject.grailsfuse.User實例的子代? – limcheekin 2009-09-05 09:19:37

+0

最新源代碼位於: http://rapidshare.com/files/275893205/one2many.zip.html – limcheekin 2009-09-05 09:41:07

1

爲了更新,我發佈了appengine-gorm插件到grails插件庫中,這是我寫這個插件以支持批量插入操作的動機。由於我無法通過使用在Google App Engine中工作的批註(@OneToMany)進行多次嘗試來建立一對多關係,因此我決定手動管理關係而不是使用映射。但是,儘管我試圖將對象保存在一對多關係的許多方面,但我面臨着谷歌應用程序引擎的請求超時。然後,我發現數據存儲區支持的低級API在一次API調用中保留了許多對象,所以這個插件就誕生了。希望這有利於你和其他人。

最後,我管理的一對多關係手動工作,沒有映射。請在http://grailsfuse.vobject.com/查看名爲GrailsFuse的現場演示應用程序。

我歡迎您的反饋和意見。請隨時在vobject dot com的limcheekin上給我發一封電子郵件。

謝謝。