-->

What is checked behind FlushMode.AUTO?

2020-07-18 08:26发布

问题:

In Hibernate, I wonder which conditions trigger flushing when flushMode is AUTO? It may be complex (or "magic") but what are the basic conditions?

Thanks

回答1:

When flush mode is FlushMode.AUTO it will happen at following times:

  • Before a query is executed
  • When a Transaction on the Hibernate API is committed
  • When the application calls session.flush() explicitly

The purpose of this mode is to avoid 'stale' state. Changes made to objects in memory may conflict with the results of the query. My understanding is that Hibernate will do a 'dirty-checking', compare original and current state of objects. If they are different and Hibernate thinks that this difference will expose you to stale data, it will try to push this state to database. It is possible because Hibernate knows what tables will be 'touched' by query and what tables it will need to update for current dirty state.

Take a look at this article:

Auto-flushing is quite intelligent in what to flush when, although some situations might be hard to detect. To improve performance, Hibernate will not simply always flush everything, but look at the tables in the database that the query touches and the data in-memory that should be stored in those tables. If there is no overlap, no data will be persisted. If an overlap is found, the whole session will be flushed, to ensure consistency.

You can also look at org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush source code.

There are couple disadvantages of FlushMode.AUTO:

  • you don't control when Hibernate will decide to execute UPDATE/INSERT/DELETE
  • potential performance issues because every object modification may lead to dirty checking + DML statement execution
  • you are not taking advantage of batching and other optimizations that Hibernate can perform when it is not trying to avoid 'stale' state

Because of these disadvantages I prefer FlushMode.COMMIT which gives you more control. In this mode Hibernate waits until you explicitly call Commit or Flush and only synchronizes in-memory state with database after that.