In that case, do you need the child to be an Entity at all?  Perhaps you
could simply embed it in the parent.

Not too sure about the JDO case, I think it might be impossible to embed a
collection unless it is of "native" values.  But with Twig you can embed an
entire collection of child objects and they can be automatically encoded as
multi-value properties that you can then query on.  It does this using the
order of multi valued properties.  For example:

name="Order name"
date="1 Dec 2009"
items.name=["An item", "Another Item", "Yet another item"]
items.price=[3.45, 1.67, 8.98]

You can now filter (or sort) by a child property and partent property.  You
cannot find a parent with a certain price AND a name but your case sounds
fine. Don't worry, Twig encodes and decodes the objects.  This only works
for one level of collection; if an item had a collection of parts Twig can
still encode it but not as ordered multi-value properties.

John

2009/12/22 Eugene Kuleshov <ekules...@gmail.com>

> On Dec 19, 2:56 am, jd <jdpatter...@gmail.com> wrote:
>
> > Could you not split your query into two?  The first to find the parent
> > and the second to return all children with an ancestor query.
>
>  In my case the main filtering criteria is actually by one of the
> child's attributes, but then I need to sort the results and present
> them using some of the parent's attributes. For example, with Order
> and OrderItem model, find all OrderItems that include the given part
> number and then sort the result according to the Order's date. So, I
> do need to preserve parent-child relationship, but don't want to
> execute N+1 queries (one for each parent referenced from the found
> children).
>
>  Also, I would like to maintain parent-child relationship, so entity
> groups are handled automatically (so I won't have to manually create
> foreign keys), i.e. I can process all parent-child chunks in one
> transaction.
>
>  Thanks
>
>  Eugene
>
>
> > On Dec 19, 3:58 am, Eugene Kuleshov <ekules...@gmail.com> wrote:
> >
> > >   It shouldn't be needed, since according to the docs [1], the Key
> > > type is only required to record parent relation in the child.
> > >   But I tried it anyways and got pretty much the same exception:
> >
> > > Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
> > >         at
> org.datanucleus.store.appengine.DatastoreTable.initializeNonPK
> > > (DatastoreTable.java:356)
> > >         at org.datanucleus.store.appengine.DatastoreTable.buildMapping
> > > (DatastoreTable.java:285)
> > >         at
> org.datanucleus.store.appengine.DatastoreManager.buildStoreData
> > > (DatastoreManager.java:405)
> > > ...
> >
> > >   regards,
> > >   Eugene
> >
> > > [1]
> http://code.google.com/appengine/docs/java/datastore/creatinggettinga...
> >
> > > On Dec 18, 2:33 pm, Rusty Wright <rwright.li...@gmail.com> wrote:
> >
> > > > Try making the parent's primary key be Key instead of String.
> >
> > > > Eugene Kuleshov wrote:
> > > > >   I am using the app engine SDK 1.3.0 with the latest Google
> Eclipse
> > > > > plugin.
> >
> > > > >   Currently, in order to be able to run queries on attributes of
> the
> > > > > parent object I have to embed parent object into a child. So, I
> have
> > > > > created the following classes
> >
> > > > > @PersistenceCapable(identityType = IdentityType.APPLICATION)
> > > > > public class Parent {
> > > > >   @PrimaryKey @Persistent String parentName;
> > > > >   @Persistent(mappedBy = "parent") List<Child> children = new
> > > > > ArrayList<Child>();
> >
> > > > >   public Parent(String parentName) { this.parentName = parentName;
> }
> > > > >   public void setParentName(String parentName) { this.parentName =
> > > > > parentName; }
> > > > >   public String getParentName() { return parentName; }
> > > > >   public List<Child> getChildren() { return children; }
> > > > >   public void addChild(Child child) {
> > > > >     child.setParent(this);
> > > > >     children.add(child);
> > > > >   }
> > > > > }
> >
> > > > > @PersistenceCapable(identityType = IdentityType.APPLICATION)
> > > > > public class Child {
> > > > >   @PrimaryKey
> > > > >   @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) Key
> > > > > childKey;
> > > > >   @Persistent String childName;
> >
> > > > >   @Embedded(
> > > > >     members = { @Persistent(name = "parentName", column =
> > > > > "childParentName") },
> > > > >     ownerMember = "children")
> > > > >   @Persistent Parent parent;
> >
> > > > >   public Child(String childName) { this.childName = childName; }
> > > > >   public void setChildName(String childName) { this.childName =
> > > > > childName; }
> > > > >   public String getChildName() { return childName; }
> > > > >   public void setParent(Parent parent) { this.parent = parent; }
> > > > >   public Parent getParent() { return parent; }
> > > > > }
> > > > >   and then I created a simple test to verify if I can persist and
> run
> > > > > queries on those objects:
> >
> > > > > public class ParentTest {
> > > > >   public static void main(String[] args) {
> > > > >     Parent parent1 = new Parent("parent1");
> > > > >     parent1.addChild(new Child("child1"));
> > > > >     parent1.addChild(new Child("child2"));
> >
> > > > >     Parent parent2 = new Parent("parent2");
> > > > >     parent2.addChild(new Child("child3"));
> >
> > > > >     ApiProxy.setEnvironmentForCurrentThread(new TestEnvironment());
> > > > >     ApiProxy.setDelegate(new ApiProxyLocalImpl(new File(".")) { });
> >
> > > > >     ApiProxyLocalImpl proxy = (ApiProxyLocalImpl)
> ApiProxy.getDelegate
> > > > > ();
> > > > >     proxy.setProperty(LocalDatastoreService.NO_STORAGE_PROPERTY,
> > > > > Boolean.TRUE.toString());
> >
> > > > >     PersistenceManagerFactory pmf =
> > > > > JDOHelper.getPersistenceManagerFactory("transactions-optional");
> > > > >     PersistenceManager pm = pmf.getPersistenceManager();
> > > > >     Transaction tx = pm.currentTransaction();
> > > > >     try {
> > > > >       tx.begin();
> > > > >       pm.makePersistent(parent1);
> > > > >       tx.commit();
> >
> > > > >       tx.begin();
> > > > >       pm.makePersistent(parent2);
> > > > >       tx.commit();
> >
> > > > >       Query query2 = pm.newQuery(Child.class);
> > > > >       query2.setFilter("parent.parentName==parentNameParam");
> > > > >       query2.declareParameters("java.lang.String parentNameParam");
> > > > >       List<Child> results2 = (List<Child>) query2.executeWithArray
> > > > > ("parent1");
> > > > >       System.err.println(results2);
> > > > >     } finally {
> > > > >       if (tx.isActive()) {
> > > > >         tx.rollback();
> > > > >       }
> > > > >       pm.close();
> > > > >     }
> > > > >   }
> > > > > }
> >
> > > > >   The DataNucleus Enhancer runs ok on the above code, but when I
> run
> > > > > my test app, I am getting an IndexOutOfBoundException from
> somewhere
> > > > > in the DataNucleus internals:
> >
> > > > > Exception in thread "main"
> java.lang.ArrayIndexOutOfBoundsException: 0
> > > > >    at
> org.datanucleus.store.appengine.DatastoreTable.initializeNonPK
> > > > > (DatastoreTable.java:356)
> > > > >    at org.datanucleus.store.appengine.DatastoreTable.buildMapping
> > > > > (DatastoreTable.java:285)
> > > > >    at
> org.datanucleus.store.appengine.DatastoreManager.buildStoreData
> > > > > (DatastoreManager.java:405)
> > > > >    at org.datanucleus.store.appengine.DatastoreManager.newStoreData
> > > > > (DatastoreManager.java:363)
> > > > >    at org.datanucleus.store.AbstractStoreManager.addClasses
> > > > > (AbstractStoreManager.java:788)
> > > > >    at org.datanucleus.store.AbstractStoreManager.addClass
> > > > > (AbstractStoreManager.java:759)
> > > > >    at
> org.datanucleus.store.mapped.MappedStoreManager.getDatastoreClass
> > > > > (MappedStoreManager.java:358)
> > > > >    at
> org.datanucleus.store.appengine.DatastoreManager.getDatastoreClass
> > > > > (DatastoreManager.java:631)
> > > > >    at
> > > > >
> org.datanucleus.store.appengine.DatastoreFieldManager.buildMappingConsumer
> > > > > (DatastoreFieldManager.java:1008)
> > > > >    at
> > > > >
> org.datanucleus.store.appengine.DatastoreFieldManager.buildMappingConsumer
> > > > > (DatastoreFieldManager.java:998)
> > > > >    at org.datanucleus.store.appengine.DatastoreFieldManager.<init>
> > > > > (DatastoreFieldManager.java:133)
> > > > >    at org.datanucleus.store.appengine.DatastoreFieldManager.<init>
> > > > > (DatastoreFieldManager.java:167)
> > > > >    at
> > > > >
> org.datanucleus.store.appengine.DatastorePersistenceHandler.insertPreProces
> s
> > > > > (DatastorePersistenceHandler.java:316)
> > > > >    at
> > > > >
> org.datanucleus.store.appengine.DatastorePersistenceHandler.insertObjects
> > > > > (DatastorePersistenceHandler.java:236)
> > > > >    at
> > > > >
> org.datanucleus.store.appengine.DatastorePersistenceHandler.insertObject
> > > > > (DatastorePersistenceHandler.java:225)
> > > > >    at
> org.datanucleus.state.JDOStateManagerImpl.internalMakePersistent
> > > > > (JDOStateManagerImpl.java:3185)
> > > > >    at org.datanucleus.state.JDOStateManagerImpl.makePersistent
> > > > > (JDOStateManagerImpl.java:3161)
> > > > >    at org.datanucleus.ObjectManagerImpl.persistObjectInternal
> > > > > (ObjectManagerImpl.java:1298)
> > > > >    at org.datanucleus.ObjectManagerImpl.persistObject
> > > > > (ObjectManagerImpl.java:1175)
> > > > >    at org.datanucleus.jdo.JDOPersistenceManager.jdoMakePersistent
> > > > > (JDOPersistenceManager.java:669)
> > > > >    at org.datanucleus.jdo.JDOPersistenceManager.makePersistent
> > > > > (JDOPersistenceManager.java:694)
> > > > >    at org.testgae.ParentTest.main(ParentTest.java:38)
> >
> > > > >   Am I doing something wrong or there is some other way to have
> parent-
> > > > > child relationship that provides some mechanism include paren'ts
> > > > > attributes in query criteria?
> >
> > > > >   Thanks
> >
> > > > >   Eugene
> >
> > > > > --
> >
> > > > > You received this message because you are subscribed to the Google
> Groups "Google App Engine for Java" group.
> > > > > To post to this group, send email to
> google-appengine-j...@googlegroups.com.
> > > > > To unsubscribe from this group, send email to
> google-appengine-java+unsubscr...@googlegroups.com<google-appengine-java%2bunsubscr...@googlegroups.com>
> .
> > > > > For more options, visit this group athttp://
> groups.google.com/group/google-appengine-java?hl=en.
>
> --
>
> You received this message because you are subscribed to the Google Groups
> "Google App Engine for Java" group.
> To post to this group, send email to
> google-appengine-j...@googlegroups.com.
> To unsubscribe from this group, send email to
> google-appengine-java+unsubscr...@googlegroups.com<google-appengine-java%2bunsubscr...@googlegroups.com>
> .
> For more options, visit this group at
> http://groups.google.com/group/google-appengine-java?hl=en.
>
>
>

--

You received this message because you are subscribed to the Google Groups 
"Google App Engine for Java" group.
To post to this group, send email to google-appengine-j...@googlegroups.com.
To unsubscribe from this group, send email to 
google-appengine-java+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en.


Reply via email to