Understanding isolation levels 事务隔离级别
from : Hibernate In Action:
The load() method is older; get() was added to Hibernate’s API due to user
request. The difference is trivial:
■ If load() can’t find the object in the cache or database, an exception is
thrown. The load() method never returns null. The get() method returns
null if the object can’t be found.
■ The load() method may return a proxy instead of a real persistent instance.
A proxy is a placeholder that triggers the loading of the real object when it’s
accessed for the first time; we discuss proxies later in this section. On the
other hand, get() never returns a proxy.
Choosing between get() and load() is easy: If you’re certain the persistent
object exists, and nonexistence would be considered exceptional, load() is a
good option. If you aren’t certain there is a persistent instance with the given
identifier, use get() and test the return value to see if it’s null. Using load() has
a further implication: The application may retrieve a valid reference (a proxy) to a
persistent instance without hitting the database to retrieve its persistent state. So
load() might not throw an exception when it doesn’t find the persistent object
in the cache or database; the exception would be thrown later, when the proxy
is accessed.
Introducing HQL:
Query q = session.createQuery("from User u where u.firstname = :fname");
q.setString("fname", "Max");
List result = q.list();
riteria criteria=session.createCriteria(Message.class);
criteria.add(Expression.like("text", "_的%"));
List results = criteria.list();
for (Object object : results) {
if(object instanceof Message){
Message msg=(Message)object;
System.err.println(String.format("id=%d,msg=%s", msg.getId(), msg.getText()));
}
}
#######################################################################
Understanding isolation levels
Databases (and other transactional systems) attempt to ensure transaction isolation,
meaning that, from the point of view of each concurrent transaction, it appears
that no other transactions are in progress.
Traditionally, this has been implemented using locking. A transaction may place
a lock on a particular item of data, temporarily preventing access to that item by
other transactions. Some modern databases such as Oracle and PostgreSQL implement
transaction isolation using multiversion concurrency control, which is generally
considered more scalable. We’ll discuss isolation assuming a locking model (most
of our observations are also applicable to multiversion concurrency).
This discussion is about database transactions and the isolation level provided
by the database. Hibernate doesn’t add additional semantics; it uses whatever is
available with a given database. If you consider the many years of experience that
database vendors have had with implementing concurrency control, you’ll clearly
see the advantage of this approach. Your part, as a Hibernate application developer,
is to understand the capabilities of your database and how to change the database
isolation behavior if needed in your particular scenario (and by your data
integrity requirements).
First, let’s look at several phenomena that break full transaction isolation. The
ANSI SQL standard defines the standard transaction isolation levels in terms of
which of these phenomena are permissible:
■ Lost update—Two transactions both update a row and then the second transaction
aborts, causing both changes to be lost. This occurs in systems that
don’t implement any locking. The concurrent transactions aren’t isolated.
■ Dirty read—One transaction reads changes made by another transaction that
hasn’t yet been committed. This is very dangerous, because those changes
might later be rolled back.
■ Unrepeatable read—A transaction reads a row twice and reads different state
each time. For example, another transaction may have written to the row,
and committed, between the two reads.
■ Second lost updates problem—A special case of an unrepeatable read. Imagine
that two concurrent transactions both read a row, one writes to it and commits,
and then the second writes to it and commits. The changes made by
the first writer are lost.
■ Phantom read—A transaction executes a query twice, and the second result
set includes rows that weren’t visible in the first result set. (It need not necessarily
be exactly the same query.) This situation is caused by another transaction
inserting new rows between the execution of the two queries.
Now that you understand all the bad things that could occur, we can define the various
transaction isolation levels and see what problems they prevent.
Isolation levels
The standard isolation levels are defined by the ANSI SQL standard but aren’t particular
to SQL databases. JTA defines the same isolation levels, and you’ll use these
levels to declare your desired transaction isolation later:
■ Read uncommitted—Permits dirty reads but not lost updates. One transaction
may not write to a row if another uncommitted transaction has already written
to it. Any transaction may read any row, however. This isolation level
may be implemented using exclusive write locks.
■ Read committed—Permits unrepeatable reads but not dirty reads. This may
be achieved using momentary shared read locks and exclusive write locks.
Reading transactions don’t block other transactions from accessing a row.
However, an uncommitted writing transaction blocks all other transactions
from accessing the row.
■ Repeatable read—Permits neither unrepeatable reads nor dirty reads. Phantom
reads may occur. This may be achieved using shared read locks and exclusive
write locks. Reading transactions block writing transactions (but not other
reading transactions), and writing transactions block all other transactions.
■ Serializable—Provides the strictest transaction isolation. It emulates serial
transaction execution, as if transactions had been executed one after
another, serially, rather than concurrently. Serializability may not be implemented
using only row-level locks; there must be another mechanism that
prevents a newly inserted row from becoming visible to a transaction that
has already executed a query that would return the row.
It’s nice to know how all these technical terms are defined, but how does that help
you choose an isolation level for your application?