Michael Bayer wrote: > > On Aug 17, 2006, at 5:58 PM, Daniel Miller wrote: > >> Suggested behavior: >> instead of immediately registering objects that are added to a collection >> as "new", the registration should be deferred until the session is flushed. >> On session.flush() any object "u" with a non-persistent child "a" and a >> cascading save rule will cause "a" to be persisted at that time. > > Keep in mind this approach, for which there is a patch attached for you > to try out,
Thanks, I'll try it out and let you know what happens. > would behave inconsistently as compared to a setup that is > using a contextual session, where objects get saved to the session > unconditionally upon construction (i.e. cascade is more or less > superfluous). this errant behavior would still remain in that case. Yes, and in my opinion that's fine. I think only fairly simple things can be done with that fully automatic save behavior (it's making a lot of assumptions that don't always hold up in more complex situations), and edge cases like this will either require an explicit delete() or a switch to a manual save mode. My use case doesn't really apply in the case of an automatic save() because I'm dealing with a User instance that has been registered as new (saved) and an Address instance that is transient (not saved). Actually Hibernates "inverse=True" marker on relationships is starting to look even better now (you may remember that I had brought that up in another thread). In this case collection membership is controlling child object persistence. i.e. a = Address u.addresses.append(a) # "a" is now "new" (marked for save) u.addresses.remove(a) # "a" is now "transient" (marked for delete) Note that this is only useful in some situations and therefore the inverse=True marker would be handy to tell SA which end of the relationship is controlling the lifecycle of new/deleted objects. > the idea that I had about the unit of work, long ago, was that > everything could be inside of it, and it would figure everything out; > insuring that certain objects dont go into the session at all as a > method of insuring the correct flush operations wasnt part of the plan, > since that puts extra responsibilities on the programmer to make sure > only the "right" objects go into the Session, and as you know there > wasnt really any way to even do it back then since everything was > threadlocal. I'm starting to change my mind about the suggested behavior I had listed in the test case. If list membership is really controlling whether an object is persistent or transient, then that suggested behavior might be wrong. How about this instead: If collection membership denotes the lifecycle of related objects then an object "addr" is registered as "new" in the session when "addr" is added to collection "u.addresses" and is registered as "deleted" when "addr" is removed from "u.addresses". This differs from my original suggestion in that it does not defer the association with a session until flush(). Instead it just balances the new registration with a corresponding delete registration on append() and remove() respectively. How does that sound? > > Hibernate's model is very different from this, and its a lot less > "smart" about these kinds of things (which is not completely a bad > thing). such as today I noticed if you save() the same object a second > time in the session, it goofily inserts it again into the table, and > then upon cascading to associated collections trips over itself with > inappropriate error messages and such. > > unfortunately we've gone pretty far down the road of "auto-save" and > this particular issue seems to be extremely difficult to detect. > Classes that are in an "orphanable child" relationship would need to be > flagged and get an extra step to make sure they have a parent regardless > of there being any parent to start with. right now, they are only > detected as part of the "deleted items" of a particular parent's > collection (although we are able to detect if they've been moved to a > new parent). > > just out of curiousity, what do you think should happen if we did this: > > session = create_session() > a = Address() > session.save(a) > session.flush() > > note that no User was ever created at all. should the Address be saved > ? I think it should not, since the Address class is in a relationship > that says "delete-orphan"; orphaned Address objects should not be > saved. this would basically be the logic im thinking of. deferring > the save() cascade doesnt address this issue. This should raise an exception because the Address instance has been explicitly saved in the session without an associated User instance. The cascade="all, delete-orphan" refers to orphaned objects that once had a parent (i.e. when the parent is deleted, the children are also deleted), not new objects that never had a parent (that's an error condition). My example on the other hand (with my updated suggested behavior) would not raise an exception: # case 1 u = User() a = Address() session.save(u) # "u" is now "new" in the session u.addresses.append(a) # "a" is now "new" in the session u.addresses.remove(a) # "a" is now "transient" session.delete(u) # "u" is now "transient" session.flush() > > So with regards to the "deferred save" approach, this is a fundamental > behavior change and its not clear at all to me if existing applications > are going to play well with it; as their new objects are now not in the > session until flush. it also could create confusion as turning on > "threadlocal" makes a bigger difference now. and im not sure if its > even the right way to go since it doenst fully enforce the "orphaned" > relationship semantics. (on the other hand, it might be good enough for > now). The more I think about that deferred save suggestion the more I think it could cause problems and confusion. I think we just need a way to tell a collection that "when I append an object it should be saved and when I remove an object it should be deleted", and a way to turn that behavior off when it is not wanted (i.e. inverse=True). I'll still give your patch a try just to see if it works. And I'll try to work on tests if I have time as well. Good night. ~ Daniel ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 _______________________________________________ Sqlalchemy-users mailing list Sqlalchemy-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/sqlalchemy-users