堆栈溢出使用JDO以双向无主一对一关系访问GAE实体

时间:2012-09-18 01:44:08

标签: google-app-engine jdo datanucleus

我正在为Google App Engine编写Java应用程序。我有两个实体需要建模为双向无主一对一关系:

第一个对象'ContainableObject'

@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")
public class ContainableObject {

/*=== Data Model ===*/
@PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Long key;

@Persistent
@Unowned
private Container container;

和第二个'容器'

@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")
public class Container {

/*=== Data Model ===*/
@PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Long key;

@Persistent
@Unowned
private ContainableObject containable;

Container可以为空或包含一个ContainableObject。 ContainableObject可以在Container中,可以在Container对象之间移动,也可以没有Container。我需要能够从Container获得 - > ContainableObject和ContainableObject - >容器

我正在使用datanucleus插件的v2。通过maven运行集成测试这个模型运行得很好,但是当我尝试通过我的REST API访问它时,我得到了堆栈溢出:

java.lang.StackOverflowError
at java.util.concurrent.FutureTask.<init>(FutureTask.java:45)
at java.util.concurrent.AbstractExecutorService.newTaskFor(AbstractExecutorService.java:72)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:91)
at com.google.appengine.tools.development.ApiProxyLocalImpl$PrivilegedApiAction.run(ApiProxyLocalImpl.java:277)
at com.google.appengine.tools.development.ApiProxyLocalImpl$PrivilegedApiAction.run(ApiProxyLocalImpl.java:262)
at java.security.AccessController.doPrivileged(Native Method)
at com.google.appengine.tools.development.ApiProxyLocalImpl.doAsyncCall(ApiProxyLocalImpl.java:216)
at com.google.appengine.tools.development.ApiProxyLocalImpl.makeAsyncCall(ApiProxyLocalImpl.java:179)
at com.google.apphosting.api.ApiProxy.makeAsyncCall(ApiProxy.java:184)
at com.google.appengine.api.datastore.DatastoreApiHelper.makeAsyncCall(DatastoreApiHelper.java:59)
at com.google.appengine.api.datastore.AsyncDatastoreServiceImpl.doBatchGetBySize(AsyncDatastoreServiceImpl.java:351)
at com.google.appengine.api.datastore.AsyncDatastoreServiceImpl.get(AsyncDatastoreServiceImpl.java:296)
at com.google.appengine.api.datastore.DatastoreServiceImpl$1.runInternal(DatastoreServiceImpl.java:78)
at com.google.appengine.api.datastore.DatastoreServiceImpl$1.runInternal(DatastoreServiceImpl.java:75)
at com.google.appengine.api.datastore.TransactionRunner.runInTransaction(TransactionRunner.java:31)
at com.google.appengine.api.datastore.DatastoreServiceImpl.get(DatastoreServiceImpl.java:75)
at com.google.appengine.api.datastore.DatastoreServiceImpl.get(DatastoreServiceImpl.java:62)
at com.google.appengine.datanucleus.WrappedDatastoreService.get(WrappedDatastoreService.java:60)
at com.google.appengine.datanucleus.FetchFieldManager.lookupOneToOneChild(FetchFieldManager.java:426)
at com.google.appengine.datanucleus.FetchFieldManager.fetchRelationField(FetchFieldManager.java:341)
at com.google.appengine.datanucleus.FetchFieldManager.fetchObjectField(FetchFieldManager.java:248)
at org.datanucleus.state.AbstractStateManager.replacingObjectField(AbstractStateManager.java:2228)
at com.whatever.ContainableObject.jdoReplaceField(ContainableObject.java)
at com.whatever.ContainableObject.jdoReplaceFields(ContainableObject.java)
at org.datanucleus.state.JDOStateManager.replaceNonLoadedFields(JDOStateManager.java:1988)
at com.google.appengine.datanucleus.EntityUtils$1.fetchNonLoadedFields(EntityUtils.java:976)
at org.datanucleus.ObjectManagerImpl.findObject(ObjectManagerImpl.java:2857)
at com.google.appengine.datanucleus.EntityUtils.entityToPojo(EntityUtils.java:1013)
at com.google.appengine.datanucleus.FetchFieldManager.lookupOneToOneChild(FetchFieldManager.java:427)
at com.google.appengine.datanucleus.FetchFieldManager.fetchRelationField(FetchFieldManager.java:341)
at com.google.appengine.datanucleus.FetchFieldManager.fetchObjectField(FetchFieldManager.java:248)
at org.datanucleus.state.AbstractStateManager.replacingObjectField(AbstractStateManager.java:2228)
at com.whatever.Container.jdoReplaceField(Container.java)
at com.whatever.Container.jdoReplaceFields(Container.java)
at org.datanucleus.state.JDOStateManager.replaceNonLoadedFields(JDOStateManager.java:1988)
at com.google.appengine.datanucleus.EntityUtils$1.fetchNonLoadedFields(EntityUtils.java:976)
at org.datanucleus.ObjectManagerImpl.findObject(ObjectManagerImpl.java:2857)
at com.google.appengine.datanucleus.EntityUtils.entityToPojo(EntityUtils.java:1013)
at com.google.appengine.datanucleus.FetchFieldManager.lookupOneToOneChild(FetchFieldManager.java:427)
at com.google.appengine.datanucleus.FetchFieldManager.fetchRelationField(FetchFieldManager.java:341)
at com.google.appengine.datanucleus.FetchFieldManager.fetchObjectField(FetchFieldManager.java:248)
at org.datanucleus.state.AbstractStateManager.replacingObjectField(AbstractStateManager.java:2228)
at com.whatever.ContainableObject.jdoReplaceField(ContainableObject.java)
at com.whatever.ContainableObject.jdoReplaceFields(ContainableObject.java)
at org.datanucleus.state.JDOStateManager.replaceNonLoadedFields(JDOStateManager.java:1988)
at com.google.appengine.datanucleus.EntityUtils$1.fetchNonLoadedFields(EntityUtils.java:976)
at org.datanucleus.ObjectManagerImpl.findObject(ObjectManagerImpl.java:2857)
at com.google.appengine.datanucleus.EntityUtils.entityToPojo(EntityUtils.java:1013)
at com.google.appengine.datanucleus.FetchFieldManager.lookupOneToOneChild(FetchFieldManager.java:427)
at com.google.appengine.datanucleus.FetchFieldManager.fetchRelationField(FetchFieldManager.java:341)
at com.google.appengine.datanucleus.FetchFieldManager.fetchObjectField(FetchFieldManager.java:248)
at org.datanucleus.state.AbstractStateManager.replacingObjectField(AbstractStateManager.java:2228)
at com.whatever.Container.jdoReplaceField(Container.java)
at com.whatever.Container.jdoReplaceFields(Container.java)
at org.datanucleus.state.JDOStateManager.replaceNonLoadedFields(JDOStateManager.java:1988)
at com.google.appengine.datanucleus.EntityUtils$1.fetchNonLoadedFields(EntityUtils.java:976)

这是对此进行建模的错误方法,还是我发现了AppEngine错误?

2 个答案:

答案 0 :(得分:1)

您说它是双向关系,但您在关系的一侧没有“mappedBy”。所以它目前是2 1-1 uni 关系。

如果打算成为2 1-1 uni关系,那么你需要在GAE JDO / JPA插件项目中向Google报告问题并使用测试用例来重现它。

答案 1 :(得分:0)

我想问题是你的类ContainableObject有一个对Container类型的对象的引用,并且在类Container中有一个对ContainableObject类型的对象的引用,所以它可能会创建一个可能驱动疯狂JDO的循环引用。 / p>

尝试摆脱引用,看看是否有效。