日期:2014-05-16 浏览次数:20476 次
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