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

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

A quick disclaimer...

Although I put in a great effort into researching all the topics I cover, mistakes can happen. Use of any information from my blog posts should be at own risk and I do not hold any liability towards any information misuse or damages caused by following any of my posts.

All content and opinions expressed on this Blog are my own and do not represent the opinions of my employer (Oracle). Use of any information contained in this blog post/article is subject to this disclaimer.
Hi! You can search my blog here ⤵
NOTE: (2022) This Blog is no longer maintained and I will not be answering any emails or comments.

I am now focusing on Atari Gamer.