Search This Blog

Tuesday 21 February 2012

Write-Behind Technique In Hibernate

Calling session.save(entity) in the code does not cause an immediate SQL insert to be fired. Similarly  session.delete(entity) or session.update(entity) will not result immediately in the execution of the sql delete or update queries being fired.
When objects associated with the persistence context are modified, the changes are not immediately propagated to the database.
What Hibernate does is instead collect all such database operations associated with a transaction, creating the minimum set of sql queries and executing them. This gives us two advantages -
  1. Every property change in the entity does not cause a separate sql update to be executed.
  2. Avoiding unwanted SQL queries ensures minimum trips to database thus reducing the network latency
  3. In case of multiple updates/inserts or deletes, Hibernate is able to make use of the JDBC Batch API to optimize performance.
This delayed execution of sql queries is known as transactional write behind. On calling a transaction.commit(), Hibernate flushes all the sql to the database. This flushing also happens :
  1. Before a query is executed. Hibernate does not flush before every query. The flush is performed only if the sql statements in the session will affect the result of the query.
  2. When the application calls session.flush() 
This above behavior is defined by the Hibernate Flush mode AUTO.Other values to control flush behavior are :
FlushMode.MANUAL: In this case the flush happens only if an explicit call is made to session.flush() or when it is necessary (identifier generation on save...) Consider the below example where the object does not get updated on modification or even if the update method is called.
public static void testManualFlush() {
    Session session = sessionFactory.openSession();
    session.setFlushMode(FlushMode.MANUAL);
    Transaction transaction = session.beginTransaction();
    Entity entity1 = (Entity) session.load(Entity.class, 1);
    entity1.setData("This should not be saved");
    session.update(entity1);// Object will not be updated back to the db
    transaction.commit();
}
This option is very useful for read only operations. The other options include FlushMode.ALWAYS in which case the session is flushed before every query. This is an inefficient option because all objects in the persistence context need to be checked if they are dirty.
FlushMode.COMMIT is used to ensure that the flush occurs when Transaction.commit() is called. The above code will work if we use this mode.(The update call is also not needed.)

3 comments:

  1. This comment has been removed by a blog administrator.

    ReplyDelete
  2. This comment has been removed by a blog administrator.

    ReplyDelete
  3. This comment has been removed by a blog administrator.

    ReplyDelete