Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grails: What is the difference between an unflushed session and a rolled back transaction?

I am SO confused by sessions and transactions. I basically don't see what the point of having both is, and I am very confused when to use one or the other.

What is the difference between an unflushed session and an uncommitted transaction?

I don't even know how to ask what I don't know... is there a resource that gives good examples of common session and transaction situations so I can see the difference?

like image 860
Mikey Avatar asked Mar 03 '12 00:03

Mikey


1 Answers

A transaction in Hibernate is pretty much the same as a transaction in JDBC in general. When you get the Connection from the DataSource it defaults to autocommit=true, so for the transaction that's changed to autocommit=false. That way changes get made in the database only when explicitly committed instead of each time you do an update.

Hibernate's Session does several things but in this case its function is as the 1st-level cache. It uses a concept called "transactional writebehind" for performance to queue up changes in that cache and only push them to the database when necessary. So for example if you retrieve a persistent instance and change it in a complex multi-method workflow where each method possibly makes no changes or several, only one update SQL statement is needed so Hibernate waits until necessary to aggregate them together. This is independent of whether you're running in a transaction though - that always happens.

Where the session cache and active transaction get together is flushing during an active transaction. Since Hibernate waits as long as possible to flush changes, if you're not in a transaction and you flush, the changes become persistent in the database immediately. So that's a performance optimization to reduce the number of database writes. But if you are in a transaction and you flush the session, you do push the changes to the database. But the database keeps the changes in its transaction queue. So even though they're in the database, they're not visible to other connections until you commit the transaction.

Ideally there won't be any explicit flushes, and the transaction commit will trigger a flush before the commit and that will both minimize the number of times you need to go to the database and keep uncommitted changes invisible to other callers. But you can flush as many times as you need.

One thing that will cause Hibernate to flush automatically on your behalf is queries. As I said you can make many changes to persistent instances (even deleting them) and they'll just be queued up in the session cache. But if you run a query (a dynamic finder, criteria, HQL, etc.) Hibernate can't know if the queued changes will affect your query. So it's pessimistic and flushes to be sure that everything's consistent for the query. The database will use the flushed but not committed data for your query and return the expected results. This is the reason we recommend that you use the withNewSession method when doing queries in custom domain class validators so you don't cause a flush of the current session during validation which can cause weird behavior.

like image 112
Burt Beckwith Avatar answered Oct 07 '22 01:10

Burt Beckwith