Igor Kromin |   Consultant. Coder. Blogger. Tinkerer. Gamer.

| Views: 8415
Fetching a child object by the ID of the parent using JDO had me stuck for a while. According to this article "reads, writes, and ancestor queries will always reflect the results of the commit" in the Google App Engine data store (HRD). After trying various things and reading lots of documentation and forum posts it all came down to how I modelled my objects. Now when I persist a parent object with an attached child, then immediately perform a query to fetch that child, the data returns as expected.

Here's what I had to do:
  • Define the parent object with a Key type primary key (not using IdGeneratorStrategy)
  • Define the parent object with a Key type primary key (with IdGeneratorStrategy.IDENTITY)
  • Make a reference member variable in the parent object to the child object
  • Make a reference member variable back to the parent inside the child object using 'mappedBy'
  • Define my query to use an ancestor expression



The parent class looked something like this:
@PersistenceCapable
public class Parent {
@PrimaryKey
@Persistent
private Key id;
@Persistent
private Child child;
...
public void setId(String id) {
this.id = KeyFactory.createKey(Parent.class.getSimpleName(), id);
}
public String getId() {
return id.getName();
}
}


In the above code the primary key is generated using a string ID that's passed in to the setter, when retrieving the ID, the getter extracts the 'name' part of the primary key, which is in fact the original ID.

The child class was similar to:
@PersistenceCapable
public class Child {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key id;
@Persistent(mappedBy = "child")
Parent parent;
...
}


This defines a primary key to use for the child, which is automatically generated by JDO, then a reference back to the parent is created with the mappedBy set to the variable name used in the parent object; this creates a bi-diretional relationship between the two classes.

The query to retrieve the child then looks like this:
PersistenceManager pm = pmf().getPersistenceManager();
Query q = pm.newQuery(Child.class, "parent == parentKey");
q.declareParameters("String parentKey");
Key key = KeyFactory.createKey(Parent.class.getSimpleName(), parentId);
q.execute(key);


What this does is set up a query for the Child objects while specifying that the parent should be set to the value of the parentKey parameter. They parentKey is created using the KeyFactory and the parent ID stored in the parentId variable.

-i

Have comments or feedback on what I wrote? Please share them below! Found this useful? Consider sending me a small tip.
comments powered by Disqus
Other posts you may like...