24

Just wanted your expert opinions on declarative transaction management for Spring. Here is my setup:

  1. DAO layer is plain old JDBC using Spring JdbcTemplate (No Hibernate etc)
  2. Service layer is POJO with declarative transactions as follows - save*, readonly = false, rollback for Throwable

Things work fine with above setup. However when I say get*, readonly = true, I see errors in my log file saying Database connection cannot be marked as readonly. This happens for all get* methods in service layer.

Now my questions are:

A. Do I have to set get* as readonly? All my get* methods are pure read DB operations. I do not wish to run them in any transaction context. How serious is the above error?

B. When I remove the get* configuration, I do not see the errors. Morever, all my simple get* operations are performed without transactions. Is this the way to go?

C. Why would anyone want to have transactional methods where readonly = true? Is there any practical significance of this configuration?

Thank you! As always, your responses are much appreciated!

melihcelik
  • 4,531
  • 1
  • 21
  • 25
AAK
  • 243
  • 1
  • 2
  • 4

2 Answers2

24

This post tells that the behaviour or the readOnly flag is persistence-mechanism-dependent.

C. Yes, when using hibernate, it gives performance benefits by setting the flush mode to FLUSH_NEVER (as described in the linked post)

B. Yes, JDBC calls do not require a transaction (hibernate requires one), so removing the @Transactional configuration trims all transaction management.

A. I'd assume spring is calling connection.setReadOnly(true) but your JDBC driver doesn't support this

The bottom-line is : don't use readonly transactions with plain JDBC.

And another thing - transactions are supposed to span multiple queries. Don't make your transactions too fine-grained. Make them a unit of work.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • Thank you Bozho! Clear as day. I guess I will remove the get* configuration as I am using plain JDBC. – AAK Apr 01 '10 at 20:19
  • 1
    Without a read-only transaction, you also open yourself up to the dreaded `org.hibernate.LazyInitializationException`. – Dave Nov 12 '14 at 21:15
  • In what way can I avoid org.hibernate.LazyInitializationException while suing waffle authntication manager. – Pablo Jomer Aug 27 '15 at 13:53
  • Post Link is broken [link](http://www.codeinstructions.com/2009/04/read-only-transactions-with-spring-and.html) – G 1 Aug 25 '16 at 07:01
5

A. Do I have to say get* as readonly? All my get* methods are pure read DB operations. I do not wish to run them in any transaction context. How serious is the above error?

Actually, you probably still want to run all of your get()s in the context of a transaction, to make sure that you are getting consistent reads. If on the other hand, you don't care about this, you can set the transaction level accordingly.

C. Why would anyone want to have transactional methods where readonly = true? Is there any practical significance of this configuration?

  1. To help protect against errant writes within get()` methods
  2. For optimization purposes. Not only can Hibernate make use of this information, as Bozho mentioned, but some databases/JDBC drivers can also be make use of this info.
matt b
  • 138,234
  • 66
  • 282
  • 345
  • Thank you Matt! I guess my get* methods are pretty much simple independant SQL select queries and I am not using Hibernate, so I'll turn off the setting. – AAK Apr 01 '10 at 20:20