I'm using v3.2.0, and running into a basic problem which surprisingly has had very little discussion here or elsewhere.
Short blurb: When you use versioned objects, once you get a StaleObjectException you are hosed. Your objects are all gone; you have to evict and reload them all again from the DB explicitly and integrate changes manually, which is horrible design. Am I right?
Longer story:
The context is that I have enabled versioning on my objects, and that works as expected. Now, with versioning in effect, I want my end-users to be able to say in the event of a stale object operation, "no, don't overwrite the the current data with my changes" or "yes, please overwrite the current data with my changes."
The problem is that hibernate does not provide a simple solution to perform case #2.
In case #1, it's easy; I just look for a staleobjectexception, catch it, and reload the objects and pass those back to my user indicating the error.
In case #2, I would have hoped for some sort of flag or mode that allows me to allow persistence despite the versioning error. Imagine something to the effect of "session.setIgnoreVersioning(true)". Alas there is nothing like this, and in fact the next best solution is a walloping amount of effort for what is a simple problem.
The following article discusses similar frustrations:
http://blogs.encodo.ch/news/view_article.php?id=22
Before I go further, let me restate the problem now that i've given more detail: Once we are notified of a staleobjectexception, is there a way to persist the object without having to reload the object and ALL of its cascade-linked objects?
Any strategy I've come up with is entirely more complicated than it should be, and it seems that this is because of the way hibernate behaves; if you save an object (x) and (x) or one of the objects it cascades through is stale, hibernate throws the exception only after it has already iterated through all of (x)'s cascading relationships and performed object.version = object.version + 1, which means that neither the object nor its 'subobjects' are in a usable state for saving. They all have to be reloaded, and all changes you've made have to be integrated. The idea of having that section of code having to follow through the cascading relationships is too large of a hammer for that simple nail.
In the worst case, I have an object (x) that contains an object (y) that contains an object (z), and lets say we have:
Object in the session are:
x.version = 1
y.version = 1
z.version = 1
Objects in DB are:
x.version = 1
y.version = 1
z.version = 3
session.save(x) is performed, which will throw a staleobjectexception. When session.save is called, hibernate modifies the objects under the hood incrementing each of the versions so our objects look like:
x.version = 2
y.version = 2
z.version = 2
Now all of our objects are unusable unless we manually traverse all of them and reload them. This is really bad behavior. Has anyone else run into this or thought of a solution to the problem?