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 <[email protected]> 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 [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/google-appengine-java?hl=en.
