6

If FlushMode.AUTO is set, will Hibernate flush my updated persistent object when I call session.close()?

I know that session.close() does not normally flush the session but I'm not sure how FlushMode.AUTO affects this.

From the Docs:

FlushMode.AUTO
The Session is sometimes flushed before query execution in order to ensure that queries never return stale state. This is the default flush mode.

Does this mean I can rely on Hibernate to verify my changes are flushed sometimes before my session is closed?

Small code example:

Session session = HibernateSessionFactory.getSession();  
PersistedObject p = session.get(PersistedObject.class,id);  
p.setSomeProperty(newValue);  
session.close();

UPDATE
According to the docs these are the places where the session will flush (when AUTO is used)

  • before some query executions
  • from org.hibernate.Transaction.commit()
  • from Session.flush()

This does not say anything about Session.close()

Harry Johnston
  • 35,639
  • 6
  • 68
  • 158
Ittai
  • 5,625
  • 14
  • 60
  • 97

2 Answers2

14

Will Hibernate flush my updated persistent object when calling session.close() (using FlushMode.AUTO)?

No it won't, and you should use a transaction with well defined boundaries. Quoting Non-transactional data access and the auto-commit mode:

Working nontransactionally with Hibernate

Look at the following code, which accesses the database without transaction boundaries:

Session session = sessionFactory.openSession(); 
session.get(Item.class, 123l); 
session.close(); 

By default, in a Java SE environment with a JDBC configuration, this is what happens if you execute this snippet:

  1. A new Session is opened. It doesn’t obtain a database connection at this point.
  2. The call to get() triggers an SQL SELECT. The Session now obtains a JDBC Connection from the connection pool. Hibernate, by default, immediately turns off the autocommit mode on this connection with setAutoCommit(false). This effectively starts a JDBC transaction!
  3. The SELECT is executed inside this JDBC transaction. The Session is closed, and the connection is returned to the pool and released by Hibernate — Hibernate calls close() on the JDBC Connection. What happens to the uncommitted transaction?

The answer to that question is, “It depends!” The JDBC specification doesn’t say anything about pending transactions when close() is called on a connection. What happens depends on how the vendors implement the specification. With Oracle JDBC drivers, for example, the call to close() commits the transaction! Most other JDBC vendors take the sane route and roll back any pending transaction when the JDBC Connection object is closed and the resource is returned to the pool.

Obviously, this won’t be a problem for the SELECT you’ve executed, but look at this variation:

Session session = getSessionFactory().openSession(); 
Long generatedId = session.save(item); 
session.close(); 

This code results in an INSERT statement, executed inside a transaction that is never committed or rolled back. On Oracle, this piece of code inserts data permanently; in other databases, it may not. (This situation is slightly more complicated: The INSERT is executed only if the identifier generator requires it. For example, an identifier value can be obtained from a sequence without an INSERT. The persistent entity is then queued until flush-time insertion — which never happens in this code. An identity strategy requires an immediate INSERT for the value to be generated.)

Bottom line: use explicit transaction demarcation.

Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
  • ) I just finished this passage from the link you gave me in another question to return here, refresh and see it. You are of course correct and thank you very much for clarifying this important topic for me. – Ittai Oct 14 '10 at 09:07
0

closing a session will always flush al work to the database. Flushmode.AUTO flushes work to the database when there are changes and you are quering the table with changed records.

Salandur
  • 6,409
  • 2
  • 22
  • 23
  • thanks for your answer. Can you attach some sort of reference to this statement? I've read two many postings on-line regarding this which confuse me (hence my question) and I'd appreciate a link to a certified Hibernate source. – Ittai Oct 14 '10 at 08:10
  • http://docs.jboss.org/hibernate/stable/core/reference/en/html/objectstate.html#objectstate-flushing ok I was not entirely correct. If you are using transactions, the commit will flush. If there is no active transaction, all changes are directly propagated to the database (a transaction per session-method call) – Salandur Oct 14 '10 at 08:16
  • 1
    true, since my experience is unfortunatly with oracle 9 database – Salandur Oct 14 '10 at 09:16