Hello,
I'm using an architecture pretty much resembling the application transaction with session-per-request-with-detached-objects as explained at
http://www.hibernate.org/168.html.
Now, the problem is that when I give the client an object with associated objects mapped with cascade="all" or cascade="save-update", calling saveOrUpdate() on the object also causes all the associated objects to be written to the database even though they have not changed. So if the client modifies the root of an object tree, there can be *a lot* of updates even though only one object has actually changed. Clearly this is not desirable.
So, how can this problem be solved? Hibernate cannot do an automatic dirty check for detached objects, so some kind of manual intervention is required.
1. Looping through all the associated objects and locking them to the session. LockMode.NONE doesn't seem to do any dirty checking, LockMode.READ works but it causes a SELECT of the object in question, so DB traffic doesn't decrease.
2. Looping through all the associated objects and loading them. I haven't tried this, but this should work, and the objects would be loaded from the cache. However, I would have to do some manual dirty checking between the newly loaded objects and the detached objects and copying changed properties to the new object, right?
3. Manual dirty checking with a non-persistent "boolean dirty" property for every persistent object. I.e. when a persistent property is modified, mark the object as dirty.
3a. When saveOrUpdate, don't use cascade="all" or cascade="save-update", but rather loop through all the associated objects and saveOrUpdate them if they are marked dirty, otherwise do nothing.
3b. Use cascading, have persistent objects implement the LifeCycle interface. Override the OnUpdate() method to VETO the updating if the "dirty" property is false.
3c. Use cascading. Make an interceptor which uses the findDirty() method to check if the object is dirty. A problem with this approach is that I would need an interceptor for every persistent class since findDirty is supposed to return an int[] containing indexes of the dirty properties. Or can I cheat, and just return some bogus int[] array as long as I don't use dynamic-update?
4. Some other approach, what?
I guess I'm not the only one to encounter this problem, so how have other people solved it? Is there any "best practice" way?