Search This Blog

Friday, 17 February 2012

Automatic Dirty Checking

Consider the below code which loads a simple Entity from the database and updates it.
public static void testUpdate() {
    Session session = sessionFactory.openSession();
    Transaction transaction = session.beginTransaction();    
    Entity entity = (Entity) session.load(Entity.class, 1);
    entity.setData("Updating the data");
    transaction.commit();
    session.close();
}
Although we haven't made any session.update(entity) call, the logs indicate that the database record was updated successfully.
3094 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister  - Upda
ting entity: [com.model.Entity#1]
3094 [main] DEBUG org.hibernate.jdbc.AbstractBatcher  - about to open PreparedSt
atement (open PreparedStatements: 0, globally: 0)
3094 [main] DEBUG org.hibernate.SQL  - 
    update
        Entity 
    set
        DATA=? 
    where
        id=?
If the update call wasn't made then how did the update occur ??The reason for the successful save is automatic dirty checking.
At the end of every transaction, Hibernate takes it upon itself to persist back to the database all objects that have been modified in this transaction. 
Hibernate is capable of detecting all objects that have been modified or are dirty.  This it does with the help of the PersistenceContext.
Within the PersistenceContext Hibernate has a copy of all the persistent objects that were loaded from the database. It compares the persistent objects with these objects to detect the objects that have been modified. This is the default implementation.
At the end of the transaction, Hibernate acquires the appropriate table locks, updates the records in table and releases all acquired locks thereby completing the transaction.
Hibernate allows for the implementation of our own custom dirty checking algorithm too. This is done by implementing the findDirty() method of org.hibernate.Interceptor interface for a session.
class DirtyChecker implements Interceptor {
    
    @Override
    public int[] findDirty(Object entity, Serializable id,
            Object[] currentState, Object[] previousState,
            String[] propertyNames, Type[] types) {
        // The return value determines whether the entity is updated
        // It returns an array of property indices indicating the entity is dirty
        // or an empty array - the entity is not dirty        
        return null;
    }
//more methods ...
}

2 comments:

  1. Nice post but did not understand in depth.

    ReplyDelete
  2. read this also
    http://vladmihalcea.com/2014/08/21/the-anatomy-of-hibernate-dirty-checking/

    ReplyDelete