For a scenario where you have a detached object and you know that the object state has not changed you might want Hibernate not to perform the redundant update call. Also, there could be a case where you would like to perform your own custom dirty-checks instead of leaving the task to Hibernate. There is a pretty good feature in Hibernate called Interceptors that you could use to control these actions. Let's get in to some details --
Let's say you have a Domain Object, MyObject, and your object is capable of determining whenever the state gets dirty and it responds by isDirty() call. That means whenever you make a callmyObject.isDirty() it would respond back whether the object is dirty or not.
Create an Interceptor class, let's call it DirtyCheckInterceptor. You may either implement the Hibernate's Inteceptor interface OR extend the EmptyInterceptor and use it as a base class. They have got quite a few hooks where you could intercept the calls through out the life cycle. One method we're interested at this point is findDirty(), see a sample implementation below:
1 | public int [] findDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types) { |
2 | if (entity.isDirty()) { |
3 | return null ; |
4 | } |
5 | return new int [ 0 ]; |
6 | } |
As per the documentation, the return value of the findDirty method determines whether the entity is updated --
- an array of property indices - the entity is dirty
- and empty array - the entity is not dirty
- null - use Hibernate's default dirty-checking algorithm
Let's talk first about line 6 of the above implementation -- this is a scenario where the object has made the determination that it is not dirty so return an empty array to indicate hibernate that the object is not dirty, and so don't perform any updates. If that is not the case and the object is dirty, you could return null (line 4 above) to indicate Hibernate that the Object is dirty so perform the default dirty check algorithm and follow the due course. Also, if you don't want Hibernate to perform the dirty check at all and you would like to take care of it by your own algorithm, you can very well do that and pass the an array of property indices that are dirty as return value.
Hibernate's FlushEntityEventListener's onFlushEntity implementation calls the registered interceptor before making an update call.
You can set the interceptor at a session level or on a global level. For session level,
SessionFactory.openSession( new DirtyCheckInterceptor() );
A global level one,
new Configuration().setInterceptor( new DirtyCheckInterceptor() );