Hibernate version: 3.0.5 w/ MySQL and Oracle
I am dealing with some implementation issues of the "Session Per View" pattern. Two questions:
1) What is the most elegant way to handle attempts to simultaneously create two objects with the same unique key (or natural-id)? For example, in the CaveatEmptor sample app (caveatemptor.HiA-SE-3.1alpha4), what if two users attempt to create the same Category at the same time? It looks like when the second of the two user sessions goes to commit its transaction, it will get a unique constraint violation. Pretend that this isn't acceptable and we want the app to figure out before hand if it needs to persist a new instance or just update an existing one into the session.
A simple approach is to have a synchronized method in the DAO - Category getOrCreateCategory(String name, Category parent) (where parent is already in the DB). You could even optimize it so that the whole method isn't synchronized, but just the part to do a final check for existence and insert the object. However, from what I can tell from my own experience trying this approach, I believe this means that the transaction must be committed before leaving the synchronized method/block, or else other sessions that are currently open cannot see that the new item has been added and may attempt to add their own instance of it. In other words, each individual object insertion becomes its own unit of work. This totally goes against the "session-per-view" pattern, but I can't figure out what I'm doing wrong. I assume there must be something basic with DB-transactions and lock modes that I am missing.
2) On a related note, say I want to insert a set of Parent objects, each of which has one or more Child objects. Both types use surrogate keys. The Child objects also have a set of properties which form a unique key (natural-id). I have the values which form the natural-id for each of the Child objects, but I don't know which of the Child objects, if any, are already persisted in the DB. I can use a "getOrCreateChild" method like above and do a query for each, persist it if need be, and return the persisted/detached object after committing it, but this seems like "manual" cascading of save/update and I figure there has to be a better way. Is there a standard way for me to just create transient instances of all the Child objects, add them to the Parent's set of children, and then when I save the parent, have Hibernate figure out for me, based on the unique/natural key values, whether it should create a new DB entry for a Child or whether it should simply set the surrogate ID of the child with an existing, matching value?
I realize that I could probably write such a thing myself (with a custom Persistor or Interceptor I think, probably using an Example criteria - haven't researched it that far), but I feel like I'm missing something that must be common knowledge for an easier way to do this.
adTHANKSvance,
Eric
|