Why do I need Transaction in Hibernate for read-only operations?

user93796 picture user93796 · Nov 24, 2012 · Viewed 83.2k times · Source

Why do I need Transaction in Hibernate for read-only operations?

Does the following transaction put a lock in the DB?

Example code to fetch from DB:

Transaction tx = HibernateUtil.getCurrentSession().beginTransaction(); // why begin transaction?
//readonly operation here

tx.commit() // why tx.commit? I don't want to write anything

Can I use session.close() instead of tx.commit()?

Answer

Stanislav Bashkyrtsev picture Stanislav Bashkyrtsev · Nov 24, 2012

You might actually have reasons to mark transactions as read-only.

  1. Transactions for reading might look indeed strange and often people don't mark methods for transactions in this case. But JDBC will create transaction anyway, it's just it will be working in autocommit=true if different option wasn't set explicitly.
  2. But there is no guarantee that your method doesn't write into the database. If you mark method as @Transactional(readonly=true), Spring will set the JDBC transaction into a read-only mode, thus you'll dictate whether it's actually possible to write into DB in scope of this transaction. If your architecture is cumbersome and some team members may choose to put modification query where it's not expected, this flag would point you to the problematic place.
  3. Also read-only transactions can be optimized by DBs, but this of course is DB specific. E.g. MySQL added support for this only in InnoDB starting from 5.6.4 version.
  4. If you're not using JDBC directly, but rather an ORM, that might be problematic. For instance Hibernate community says that working outside of transaction might cause unpredictable behavior. This is because Hibernate will open transaction, but it won't close it on its own, thus connection will be returned to the Connection Pool with transaction being not committed. What happens then? JDBC keeps silence, thus this is implementation specific (MySQL rolls back transaction, Oracle afair commits it). This also can be configured on Connection Pool level (e.g. C3P0 gives you such an option, rollback by default).
  5. Another thing when it comes to Hibernate, Spring sets the FlushMode to MANUAL in case of read-only transactions, which leads to other optimizations like no need for dirty checks.
  6. You may want to override or set explicitly the transaction isolation level. This impacts read-transactions as well since you do or don't want to read uncommitted changes, be exposed to phantom reads, etc.

To sum up - you can go both ways, but you need to understand consequences.