Google App Engine中的JDO:如何实现多态关系?

时间:2011-01-19 15:32:39

标签: java google-app-engine google-cloud-datastore jdo

我正在研究基于GAE的应用程序,它使用JDO来访问数据存储区。我需要在持久化对象之间实现多态关系。

有抽象的父类:

@PersistenceCapable
@Inheritance(strategy = InheritanceStrategy.SUBCLASS_TABLE)
public abstract class Parent {
 @PrimaryKey
 @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
 @Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
 String id;

    // ....

还有几个孩子班:

@PersistenceCapable (identityType = IdentityType.APPLICATION)
public class Child extends Parent {

    // ....

此外,还有一个类,应该引用其中一个子类。根据{{​​3}},实现此类关系的最佳方法是存储对象的键,因此该类以下列方式查找:

@PersistenceCapable (identityType = IdentityType.APPLICATION)
public class OtherClass {

    @Persistent
    private String reference;

    // ....

我从OtherClass的实例中检索引用对象的字符串键。然后我想获得引用对象本身:它是一个Parent子类的实例。但是:

抛出JDOObjectNotFoundException异常( javax.jdo.JDOObjectNotFoundException:没有这样的对象FailedObject:... )。

  • 如果我使用pm.getObjectById(oid)方法执行此操作:

    父对象= pm.getObjectById(Parent.class,reference);

抛出FatalNucleusUserException异常( org.datanucleus.store.appengine.FatalNucleusUserException:收到查找类型为Parent的对象的请求,但提供的标识符是kind类的Key 的String表示形式)

检索另一个实体中引用的子类之一的实例的正确方法是什么?

更新:我在GAE google网上找到了getObjectById(class, key)个帖子,但坦率地说,这对我没什么帮助。

3 个答案:

答案 0 :(得分:1)

我发现JDO和App Engine存在同样的问题,所以我启动了一个为此实现解决方法的项目。 https://code.google.com/p/datanucleus-appengine-patch/ 我用我现在的代码进行的第一次测试看起来没问题,请随意尝试一下,给我一些反馈。

实际上我的解决方法可以通过两种方式解决您的问题。

  1. 我实现了一个getObjectById(class,id),它也查找作为提供的类的实例的种类。
  2. 我实现了一个getObjectById(oid),如果oid的类型是com.google.appengine.api.datastore.Key,它会对查找进行一些特殊处理,然后它会找出要返回的正确类。
  3. 我添加了一个新的注释@PolymorphicRelationship,通过存储密钥,可以轻松处理App Engine描述的变通方法。样本如下所示:
  4.  @Persist
     public Collection<Key> myChildKeys;
    
     @NotPersistent
     @PolymorphicRelationship(keyField ="myChildKeys")
     public Collection<TestChild> myChildren;
    

答案 1 :(得分:1)

我使用这种相当癌症和恶臭的反模式来克服JDO / App Engine的这种限制。

@JsonIgnore
@Persistent(mappedBy="account")
private List<XProvider> xProviders;

@JsonIgnore
@Persistent(mappedBy="account")
private List<YProvider> yProviders;

// TODO: add extra providers here and in getProviders() below...

然后获得收藏:

public List<XProvider> getXProviders() {
    if (xProviders == null) {
        xProviders = new ArrayList<XProvider>();
    }
    return xProviders;
}
//etc with other getters and setters for each collection.

public List<Provider> getProviders() {

    List<Provider> allProviders = new ArrayList<Provider>();

    // TODO: add extra providers here...
    allProviders.addAll(getXProviders());
    allProviders.addAll(getYProviders());

    return allProviders;
}

这是一个糟糕的解决方案,但风暴中的任何端口 ......

(也与此错误有关,使用接口作为集合类型http://code.google.com/p/datanucleus-appengine/issues/detail?id=207

答案 2 :(得分:0)

App Engine的JDO层目前不支持多态。事实上,我不确定JDO是否支持它。

相关问题