日期:2014-05-16 浏览次数:20530 次
zz from :
http://www.codeinstructions.com/2009/04/read-only-transactions-with-spring-and.html
Spring supports the concept of read-only transactions.  Because Spring 
doesn't provide persistence functionality itself, the semantics of 
read-only transactions depend on the underlying persistence framework 
used along with Spring.
I use Spring with Hibernate and Oracle, 
and when I looked to understand the semantics of read-only transactions 
on this specific configuration, I found that there was very little 
information on the web.  The existing information is scarce and not very
 clear, and as a result I had to do some research myself, which included
 hacking into Spring and Hibernate's source code.  Not that I don't 
enjoy spending a few late hours reading good code, but so that you don't
 have to do it yourself, here is what I found.
Spring
Spring's documentation doesn't say almost anything about what a read-only transaction really means.  The best information
 I could find was:
Read-only
 status: a read-only transaction does not modify any data. Read-only 
transactions can be a useful optimization in some cases (such as when 
using Hibernate).
That's basically all it says.  Google and a little hacking shed some light on the real meaning of the sentence above:  if
 the transaction is marked as read-only, Spring will set the Hibernate 
Session's flush mode to FLUSH_NEVER, and will set the JDBC transaction 
to read-only
.  Now lets understand what it means and what are the implications in a Hibernate/Oracle setup.
Hibernate
Hibernate
 doesn't have the concept of read-only sessions.  But when a session's 
flush mode is set to FLUSH_NEVER, which is what Spring does, two 
interesting things happen.  First, running HQL queries no longer cause 
Hibernate to flush the session state to the database, which can provide a
 dramatic performance improvement.  Secondly, Hibernate will not flush 
the changes before commiting the transaction.  But the user can still 
call Session.flush() by hand, causing any modifications to be persisted 
to database.  This is where Spring's call to Connection.setReadOnly() 
comes handy.
Oracle
When
 using the Oracle JDBC driver, calling connection.setReadOnly(true) 
translates into the statement "SET TRANSACTION READ ONLY".  This 
statement limits the types of SQL statements that can be executed during
 the transaction.  Only SELECTS (without 'FOR UPDATE') and a few other 
statements can be executed.  Specifically, no UPDATEs, DELETEs, INSERTs 
or MERGEs can be executed.  This behavior is Oracle-specific.  Other 
RDBMS can have different semantics for read only transactions or simply 
not support it at all.
By setting the JDBC connection to 
read-only, Spring prevents a distracted user from persisting changes by 
flushing the Hibernate session to the database.
Notes
As
 we saw, with the two measures taken by Spring, the transaction is 
guaranteed to be read-only through the JDBC connection, and performance 
improvements are obtained by setting the Hibernate session to 
FLUSH_NEVER.
There is one thing that doesn't happen, though.  
Even during Spring read-only transactions, Hibernate queries still save 
the state of persistent objects in the session cache.  In theory it 
wouldn't be necessary, since this state is used to detect modifications 
during session flushes.  Depeding on the size and number of objects it 
can make a huge difference in terms of memory usage.  
If you 
still want to prevent Hibernate f