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

发布于 2024-10-12 15:53:35 字数 2055 浏览 2 评论 0原文

我正在开发基于 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 {

    // ....

另外,还有一个类,它应该引用子类之一。根据“JDO 中的实体关系”的“多态关系”部分”文章,实现这种关系的最佳方法是存储对象的键,因此该类看起来如下:

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

    @Persistent
    private String reference;

    // ....

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

抛出 JDOObjectNotFoundException 异常 (javax.jdo.JDOObjectNotFoundException: No such object FailedObject:...)。

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

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

更新:我发现这个 GAE google 小组中的帖子,但坦率地说,这对我没有多大帮助。

I'm working on GAE-based applications, which uses JDO to access datastore. I need to implement polymorphic relationship between persisted objects.

There's abstract parent class:

@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;

    // ....

And several child classes:

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

    // ....

Also, there's one more class, which should have reference to one of child classes. According to "Polymorphic Relationships" section of "Entity Relationships in JDO" article, the best way to implement such relationship is to store key of an object, so this class looks in the following way:

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

    @Persistent
    private String reference;

    // ....

I retrieve string key of referenced object from instance of OtherClass. Then I would like to obtain referenced object itself: it's an instance of one of Parent subclasses. BUT:

JDOObjectNotFoundException exception is thrown (javax.jdo.JDOObjectNotFoundException: No such object FailedObject:...).

FatalNucleusUserException exception is thrown (org.datanucleus.store.appengine.FatalNucleusUserException: Received a request to find an object of kind Parent but the provided identifier is the String representation of a Key for kind Child)

What is correct way to retrieve instance of one of subclasses referenced in another entity?

UPDATE: I found this thread in GAE google group, but frankly it did not help me a lot.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

甜味拾荒者 2024-10-19 15:53:35

我发现 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 描述的解决方法。示例如下所示:

<前><代码>@Persist
公共集合我的子键;

@不持久
@PolymorphicRelationship(keyField =“myChildKeys”)
公共集合我的孩子们;

I found the same problem with JDO and App Engine, so I started a project that implements a workaround for this. https://code.google.com/p/datanucleus-appengine-patch/
My first test with the code I have now looks okay, feel free to try it out at give me some feedback.

Actually my workaround may solve your problem 2 ways.

  1. I implemented a getObjectById(class, id) that also looks for kinds that are instances of the provided class.
  2. I implemented a getObjectById(oid) that does some special handling of lookup if oid is of type com.google.appengine.api.datastore.Key, then it will figure out the correct class to return.
  3. I added a new annotation @PolymorphicRelationship that will make is easy to handle to workaround that App Engine describes, with storing the keys. Sample shown below:
 @Persist
 public Collection<Key> myChildKeys;

 @NotPersistent
 @PolymorphicRelationship(keyField ="myChildKeys")
 public Collection<TestChild> myChildren;
小瓶盖 2024-10-19 15:53:35

我正在使用这种相当癌变且有异味的反模式来绕过 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 )

I'm using this rather cancerous and smelly anti-pattern to get around this limitation of 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...

And then to get the collection:

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;
}

It's a bad solution, but any port in a storm...

(Also relates a little to this bug, using interfaces as the collection type http://code.google.com/p/datanucleus-appengine/issues/detail?id=207)

痴意少年 2024-10-19 15:53:35

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

App Engine's JDO layer doesn't currently support polymorphism. In fact, I'm not sure if JDO supports it in general or not.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文