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

NOTE: This article is 3 years or older so its information may no longer be relevant. Read on at your own discretion! Comments for this article have automatically been locked, refer to the FAQ for more details.
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

Skip down to comments...
Hope you found this post useful...

...so please read on! I love writing articles that provide beneficial information, tips and examples to my readers. All information on my blog is provided free of charge and I encourage you to share it as you wish. There is a small favour I ask in return however - engage in comments below, provide feedback, and if you see mistakes let me know.

If you want to show additional support and help me pay for web hosting and domain name registration, donations, no matter how small, are always welcome!

Use of any information contained in this blog post/article is subject to this disclaimer.
 
comments powered by Disqus
Other posts you may like...