Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does a Hibernate transaction rollback delete "session.flush()"ed entities?

I have been confused about transaction.rollback. Here is example pseudocode:

transaction = session.beginTransaction()     EntityA a = new EntityA();     session.save(a);     session.flush();     transaction.rollback(); 

What happens when this code works? Do I have the entity in the database or not?

like image 526
kommradHomer Avatar asked Mar 28 '12 13:03

kommradHomer


People also ask

What is transaction rollback in hibernate?

rollback() , Hibernate rolls-back the database transaction. Database handles rollback, thus removing newly created object.

What does flush method do in hibernate?

Flushing the session forces Hibernate to synchronize the in-memory state of the Session with the database (i.e. to write changes to the database). By default, Hibernate will flush changes automatically for you: before some query executions.

Does @transactional close session?

@Transactional helps you to extend scope of Session . Session is open first time when getCurrentSession() is executed and it is closed when transaction ends and it is flushed before transaction commits.

Does session flush commit transaction?

flush() will synchronize your database with the current state of object/objects held in the memory but it does not commit the transaction. So, if you get any exception after flush() is called, then the transaction will be rolled back.


2 Answers

Short answer: No, you won't have entity in the database.

Longer answer: hibernate is smart enough not to send insert/updates to the DB until it knows if the transaction is going to be committed or rolled back (although this behavior can be changed by setting a different FlushMode), in your case by calling flush you are forcing the SQL to be sent to the DB but you still have the DB transaction to protect you, when you call rollback the DB transaction will be rolled back removing the changes performed inside itself and hence nothing will be actually saved. Note that depending on your configured transaction isolation level perhaps other transactions will be able to see in some way the EntityA you saved for the short while between the save and the rollback. Also note that flush is called automatically when you try to read from DB, in 99% of the cases calling it explicitly is not necessary. One exception that comes to mind is when unit testing with auto rolling back tests.

like image 89
ilcavero Avatar answered Sep 22 '22 14:09

ilcavero


When you call session.save(a) Hibernate basically remembers somewhere inside session that this object has to be saved. It can decide if he wants to issue INSERT INTO... immediately, some time later or on commit. This is a performance improvement, allowing Hibernate to batch inserts or avoid them if transaction is rolled back.

When you call session.flush(), Hibernate is forced to issue INSERT INTO... against the database. The entity is stored in the database, but not yet commited. Depending on transaction isolation level it won't be seen by other running transactions. But now the database knows about the record.

When you call transaction.rollback(), Hibernate rolls-back the database transaction. Database handles rollback, thus removing newly created object.

Now consider the scenario without flush(). First of all, you never touch the database so the performance is better and rollback is basically a no-op. On the other hand if transaction isolation level is READ UNCOMMITTED, other transactions can see inserted record even before commit/rollback. Without flush() this won't happen, unless Hibernate does not decide to flush() implicitly.

like image 39
Tomasz Nurkiewicz Avatar answered Sep 21 '22 14:09

Tomasz Nurkiewicz