I agree with Jake; relationships are tricky.  Likewise with his pointing out 
that having race be in two Results will be a problem; that won't fly.

Another way would be to have a List<Result> in Race, and add your Results to 
that.  But you're still going to have parenting problems when you have the same 
runner in different races; that's where I'd store the Runner's Key in the Result.

Having the Result query the datastore seems odd to me; I was thinking of doing that but 
it seems to me that these persistent objects ought to be fairly simple data transfer 
objects and shouldn't be doing that.  The DAO does the datastore interactions.  If you 
were doing the fully layered way, with domain objects (that is, these data transfer 
objects), DAOs, and a service layer, I could see the service layer calling the DAOs, and 
then it calls the setters on the domain objects to fill in the missing stuff, like the 
Race in the Result here.  But that seems "dirty" to me; shouldn't the ORM be 
doing this for us?


Jake wrote:
Hey,

Relationships in GAE are a bit picky.  It is my understanding that you
can only persist children by way of persisting their parents.  So, in
your case, both Race and Runner are children of Result and you would
only persist the two result objects - the dependent children would be
persisted automatically.  I'm willing to bet, though, that a single
race object cannot be the child of two different parent objects,
though I'm not certain.  The details are all here:
http://code.google.com/appengine/docs/java/datastore/relationships.html

For the most part, I've found that parent/child relationships are only
useful when the two are highly related - usually when I'm extending a
class to provide more data.  (e.g. Race -> RaceDetails).

The "easy" way to get around this is to store the objects in unowned
relationships, referencing other objects by IDs as described in
http://code.google.com/appengine/docs/java/datastore/relationships.html#Unowned_Relationships.
Then, with some fancy getters/setters that automatically query the
Datastore, you end up with the same result.  See my example below.

If anyone has any other advice, though, please contribute.  I haven't
found a great way to handle this and I'm trying to avoid using GAE
specific libraries to help.

Jake

public class Race {

   private Key id;
   ...
}

public class Result {

   private Key id;
   private Key raceId;

   public Race getRace() {
       //query datastore with getObjectById(Race.class, raceId);
   }
}

On Feb 6, 7:15 pm, Rodolphe <rde...@gmail.com> wrote:
Hello,

I am very new to appengine, and I am trying a very basic model exemple: A
Race class is linked to a Runner class through a Result class

When I am running the folloging code (the full code is attached):
        Race race = new Race("Paris", new Date(), 10);

        Runner runner1 = new Runner("Smith");
        Runner runner2 = new Runner("John");

        Result result1 = new Result(race, runner1, 1);
        Result result2 = new Result(race, runner2, 2);

        PersistenceManager pm = PMF.get().getPersistenceManager();
        try {
            race = pm.makePersistent(race);

            runner1 = pm.makePersistent(runner1);
            runner2 = pm.makePersistent(runner2);

            pm.makePersistent(result1);
            pm.makePersistent(result2);
        } finally {
            pm.close();
        }

I get the following error:
Detected attempt to establish Result(4) as the parent of Runner(2) but the
entity identified by Runner(2) has already been persisted without a parent.
A parent cannot be established or changed once an object has been persisted.
org.datanucleus.store.appengine.FatalNucleusUserException: Detected attempt
to establish Result(4) as the parent of Runner(2) but the entity identified
by Runner(2) has already been persisted without a parent.  A parent cannot
be established or changed once an object has been persisted.
    at
org.datanucleus.store.appengine.DatastoreRelationFieldManager.checkForParentSwitch(DatastoreRelationFieldManager.java:204)
    at
org.datanucleus.store.appengine.DatastoreRelationFieldManager$1.setObjectViaMapping(DatastoreRelationFieldManager.java:125)
    at
org.datanucleus.store.appengine.DatastoreRelationFieldManager$1.apply(DatastoreRelationFieldManager.java:104)
    at
org.datanucleus.store.appengine.DatastoreRelationFieldManager.storeRelations(DatastoreRelationFieldManager.java:78)
    at
org.datanucleus.store.appengine.DatastoreFieldManager.storeRelations(DatastoreFieldManager.java:812)
    at
org.datanucleus.store.appengine.DatastorePersistenceHandler.insertPostProcess(DatastorePersistenceHandler.java:288)
    at
org.datanucleus.store.appengine.DatastorePersistenceHandler.insertObjects(DatastorePersistenceHandler.java:241)
    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 race.TestRace.test2(TestRace.java:58)

Any idea how I could solve this ?

Thank you in advance
Rodolphe

 TestRace.java
3KViewDownload

 Race.java
1KViewDownload

 Result.java
1KViewDownload

 Runner.java
1KViewDownload


--
0x2B | ~0x2b  --  Hamlet

--
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