John, I still hope to find a plain JDO solution that won't tie my
application to GAE-specific model and helper libraries that working
around GAE restrictions. Especially because it is not mentioned in the
docs that it is not allowed to use parent-shild relation and have
parent embedded into the child. More over, ArrayIndexOutOfBound
exception look rather suspicious and may actually mean that there is
rather issue with configuration or even with jdo runtime
implementation. It would be great to hear back from the DataNucleus
developers on that.

  Also, I would prefer to not manually inlinine parent's data into the
child because it a) cause data duplication (e.g. I have set the data
in all places upon creation); b) it makes model even worse when parent
has more then one child type (e.g. order/orderItem, order/
orderDelivery, etc). I should mention that I used an order model only
as an example and my model is a bit more complex then that.

  Thanks
  Eugene


On Dec 21, 11:53 pm, John Patterson <jdpatter...@gmail.com> wrote:
> 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
>
> ...
>
> read more »

--

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