Reputation: 7780
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:
If I do it with pm.getObjectById(oid) method:
Object object = pm.getObjectById(reference);
JDOObjectNotFoundException exception is thrown (javax.jdo.JDOObjectNotFoundException: No such object FailedObject:...).
If I do it with getObjectById(class, key) method:
Parent object = pm.getObjectById(Parent.class, reference);
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.
Upvotes: 1
Views: 1294
Reputation: 3886
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)
Upvotes: 1
Reputation: 11
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.
@Persist public Collection<Key> myChildKeys; @NotPersistent @PolymorphicRelationship(keyField ="myChildKeys") public Collection<TestChild> myChildren;
Upvotes: 1
Reputation: 101139
App Engine's JDO layer doesn't currently support polymorphism. In fact, I'm not sure if JDO supports it in general or not.
Upvotes: 0