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