开发者

Query in a transaction with an ancestor filter in Google App Engine (Java)

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?


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.


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


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜