views:

46

answers:

2

How can I configure Hibernate to apply all saves, updates, and deletes to the database server immediately after the session executes each operation? By default, Hibernate enqueues all save, update, and delete operations and submits them to the database server only after a flush() operation, committing the transaction, or the closing of the session in which these operations occur.

One benefit of immediately flushing database "write" operations is that a program can catch and handle any database exceptions (such as a ConstraintViolationException) in the code block in which they occur. With late or auto-flushing, these exceptions may occur long after the corresponding Hibernate operation that caused the SQL operation.

Update:

According to the Hibernate API documentation for interface Session, the benefit of catching and handling a database exception before the session ends may be of no benefit at all: "If the Session throws an exception, the transaction must be rolled back and the session discarded. The internal state of the Session might not be consistent with the database after the exception occurs."

Perhaps, then, the benefit of surrounding an "immediate" Hibernate session write operation with a try-catch block is to catch and log the exception as soon as it occurs. Does immediate flushing of these operations have any other benefits?

+1  A: 

Look in to autocommit though it is not recommended. If your work includes more than one update or insert SQL statement, you autocommit some of the work, and then a statement fails, you have a potentially arduous task of undoing the first part of the action. It gets really fun when the 'undo' operation fails.

Anyway, here's a link that shows how to do it.

Tony Ennis
I don't want to auto commit the transaction, I simply want to flush the Hibernate session operations to the database immediately after they occur, but still within the context of a transaction that Hibernate commits when it closes the session. Can Hibernate "auto-flush" every write operation as it occurs?
Derek Mahar
+1 Didn't know about that one !
Will Marcouiller
Googling hibernate and autoflush turns up many hits. This may not be exactly what you want of course. But it's not too hard to add a flush() to each of the DAO methods that write.
Tony Ennis
This doesn't answer the question, autocommit and "eager flush" are two different things.
Pascal Thivent
yes but what the OP was asking wasn't clear to me originally.
Tony Ennis
+2  A: 

How can I configure Hibernate to apply all saves, updates, and deletes to the database server immediately after the session executes each operation?

To my knowledge, Hibernate doesn't offer any facility for that. However, it looks like Spring does and you can have some data access operations FLUSH_EAGER by turning their HibernateTemplate respectively HibernateInterceptor to that flush mode (source).

But I warmly suggest to read the javadoc carefully (I'll come back on this).

By default, Hibernate enqueues all save, update, and delete operations and submits them to the database server only after a flush() operation, committing the transaction, or the closing of the session in which these operations occur.

Closing the session doesn't flush.

One benefit of immediately flushing database "write" operations is that a program can catch and handle any database exceptions (such as a ConstraintViolationException) in the code block in which they occur. With late or auto-flushing, these exceptions may occur long after the corresponding Hibernate operation that caused the SQL operation

First, DBMSs vary as to whether a constraint violation comes back on the insert (or update ) or on the subsequent commit (this is known as immediate or deferred constraints). So there is no guarantee and your DBA might even not want immediate constraints (which should be the default behavior though).

Second, I personally see more drawbacks with immediate flushing than benefits, as explained black in white in the javadoc of FLUSH_EAGER:

Eager flushing leads to immediate synchronization with the database, even if in a transaction. This causes inconsistencies to show up and throw a respective exception immediately, and JDBC access code that participates in the same transaction will see the changes as the database is already aware of them then. But the drawbacks are:

  • additional communication roundtrips with the database, instead of a single batch at transaction commit;
  • the fact that an actual database rollback is needed if the Hibernate transaction rolls back (due to already submitted SQL statements).

And believe me, increasing the database roundtrips and loosing the batching of statements can cause major performance degradation.

Also keep in mind that once you get an exception, there is not much you can do apart from throwing your session away.

To sum up, I'm very happy that Hibernate enqueues the various actions and I would certainly not use this EAGER_FLUSH flushMode as a general setting (but maybe only for the specific operations that actually require eager, if any).

Pascal Thivent
So closing a Hibernate session effectively discards all pending update operations?
Derek Mahar
Does Hibernate also aggregate update operations into a single update at flush time?
Derek Mahar
@Derek Closing a session (which should be done outside a transaction) doesn't flush. So yes, changes are discarded. And yes, changes are made in memory until flush.
Pascal Thivent