|
I'm new to hibernate and this is a more general question on how to tackle a certain design issue.
Scenario:
I am going to build a multi-user 3-tier-application with rich client (Delphi), application server (Java-based) and database. Hibernate might be an option for the persistence layer in the server application.
Typical units of work will span several interactions between client and server, e.g. getting an objects and all 'selectable' association objects, editing the object (user think time) and saving all changes. A concrete example would look like this: the user opens a dialog that displays object A for editing. Via two combo boxes the user can create two different associations from object A to other objects, say to objects B and C. After clicking OK all changes are sent to the server to make them persistent.
I've read the hibernate documentation and it recommends using optimistic locking (long session or detached objects) with managend versioning to isolate concurrend application conversations.
Question:
Now, finally, the question: How can I give meaningful error messages to the user in case committing the second database transaction at the end of the application transaction fails? Suppose another user deletes object B while the first user is still working on object A. His user session will still try to save object A with an association to object B and another to object C. The commit will fail because object B has meanwhile been deleted by the other user. Hibernate will throw a ConstraintViolationException but that contains only a ConstraintName which seems to be a number with no obvious meaning.
In the scenario described, I would need to give the user a concrete error message saying that object B was deleted while he or she was working on object A. The user would then have the chance to choose another object to associate with object A. But from the Constraint ViolationException I see no way of telling whether object B or object C caused the problem.
I'd very much appreciate any suggestions how to go about this!
I suppose I could create pessimistic locks for objects B and C at the end of the application conversation right before the final commit. That way I would ensure that both objects still exist and nobody could delete them while they're locked. But locking them would result in two extra select-statements, which I find expensive because (a) my scenario described above won't happen very often (but it's still possible) and (b) they just seem unneccessary.
I could try to find out, which object caused the problem after the commit failed. But I've read in the docs that I'm not supposed to use the hybernate session any longer after an exception occurred. Plus it sounds like a lot of work to implement those after-checks for all use cases. I can see no generic approach.
Thanks for any suggestions.
Jens
|