2

我正在为 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 --> Container 中获取

我正在使用 v2 的 datanucleus 插件。通过 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 错误?

4

2 回答 2

1

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

如果它打算是 2 1-1 uni 关系,那么您需要在 GAE JDO/JPA 插件项目上向 Google 报告问题,并带有一个测试用例来重现它。

于 2012-09-19T07:37:41.817 回答
0

我猜问题是你的 ContainableObject 类引用了一个 Container 类型的对象,并且在 Container 类中引用了一个 ContainableObject 类型的对象,所以它可能会创建一个循环引用,这可能会导致疯狂的 JDO。

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

于 2012-09-18T01:49:26.847 回答