Reputation: 12616
The Java documentation says that an app can perform a query during a transaction, but only if it includes an ancestor filter, but there is no documentation for how to do it. Can anyone provide some example code that shows how to do this in the most concise way possible?
Upvotes: 2
Views: 2555
Reputation: 637
I struggled with this one for a while, but the following will work! The short answer is that JDO used with App Engine can definitely support Ancestor Queries, so you don't have to resort to the low level API unique to App Engine, especially in the case where you want to stick with JDO throughout your application.
Step 1:
In the child class make sure to have the following instance variable. The actual name of the variable does not matter. What is important is annotation.
@Persistent
@Extension(vendorName="datanucleus", key="gae.parent-pk", value="true")
private String mParentEncKey;
Step 2:
When querying for the child object(s) by the parent key, you want to then filter on the parentKey via the name of the instance variable you created... in this case This example is for if you want to query a set of child objects that have a property, given that you know the parent key and that property.
public static List<ChildObject> queryYourChildObjects(String parentKey, String someProperty) {
PersistenceManager pm = PMF.get().getPersistenceManager();
Query q = pm.newQuery(ChildObject.class);
q.setFilter("mParentEncKey == parentKeyParam && property == propertyParam");
q.declareParameters("String parentKeyParam, String propertyParam");
List<ChildObject> results = (List<ChildObject>) q.execute(parentKey, someProperty);
return results;
}
That's it! Hopefully that helps.
Upvotes: 2
Reputation: 12736
Try this approach:
// PersistenceManager pm = ...;
Transaction tx = pm.currentTransaction();
User user = userService.currentUser();
List<Account> accounts = new ArrayList<Account>();
try {
tx.begin();
Query query = pm.newQuery("select from Customer " +
"where user == userParam " +
"parameters User userParam");
List<Customer> customers = (List<Customer>)
query.execute(user);
query = pm.newQuery("select from Account " +
"where parent-pk == keyParam " +
"parameters Key keyParam");
for (Customer customer : customers) {
accounts.addAll((List<Account>)
query.execute(customer.key));
}
} finally {
if (tx.isActive()) {
tx.rollback();
}
}
More information is available here: http://code.google.com/appengine/docs/java/datastore/transactions.html#Uses_For_Transactions
Upvotes: 1
Reputation: 14187
If you are using the low level datastore, it is easy, as "ancestor" is a datastore concept and not a JDO/JPA concept AFAIK.
here is a link to the javadoc showing the Query constructor that takes an ancestor key
Upvotes: 0