Siêu thị PDFTải ngay đi em, trời tối mất

Thư viện tri thức trực tuyến

Kho tài liệu với 50,000+ tài liệu học thuật

© 2023 Siêu thị PDF - Kho tài liệu học thuật hàng đầu Việt Nam

manning Hibernate in Action phần 6 potx
MIỄN PHÍ
Số trang
47
Kích thước
206.2 KB
Định dạng
PDF
Lượt xem
1170

manning Hibernate in Action phần 6 potx

Nội dung xem thử

Mô tả chi tiết

Licensed to Jose Carlos Romero Figueroa <[email protected]>

158 CHAPTER 5

Transactions, concurrency, and caching

We aren’t interested in the details of direct JDBC or JTA transaction demarca￾tion. You’ll be using these APIs only indirectly.

Hibernate communicates with the database via a JDBC Connection; hence it must

support both APIs. In a stand-alone (or web-based) application, only the JDBC

transaction handling is available; in an application server, Hibernate can use JTA.

Since we would like Hibernate application code to look the same in both managed

and non-managed environments, Hibernate provides its own abstraction layer, hid￾ing the underlying transaction API. Hibernate allows user extension, so you could

even plug in an adaptor for the CORBA transaction service.

Transaction management is exposed to the application developer via the Hiber￾nate Transaction interface. You aren’t forced to use this API—Hibernate lets you

control JTA or JDBC transactions directly, but this usage is discouraged, and we

won’t discuss this option.

5.1.2 The Hibernate Transaction API

The Transaction interface provides methods for declaring the boundaries of a data￾base transaction. See listing 5.1 for an example of the basic usage of Transaction.

Listing 5.1 Using the Hibernate Transaction API

Session session = sessions.openSession();

Transaction tx = null;

try {

tx = session.beginTransaction();

concludeAuction();

tx.commit();

} catch (Exception e) {

if (tx != null) {

try {

tx.rollback();

} catch (HibernateException he) {

//log he and rethrow e

}

}

throw e;

} finally {

try {

session.close();

} catch (HibernateException he) {

throw he;

}

}

Licensed to Jose Carlos Romero Figueroa <[email protected]>

Understanding database transactions 159

The call to session.beginTransaction() marks the beginning of a database trans￾action. In the case of a non-managed environment, this starts a JDBC transaction

on the JDBC connection. In the case of a managed environment, it starts a new JTA

transaction if there is no current JTA transaction, or joins the existing current JTA

transaction. This is all handled by Hibernate—you shouldn’t need to care about

the implementation.

The call to tx.commit()synchronizes the Session state with the database. Hiber￾nate then commits the underlying transaction if and only if beginTransaction()

started a new transaction (in both managed and non-managed cases). If begin￾Transaction() did not start an underlying database transaction, commit() only syn￾chronizes the Session state with the database; it’s left to the responsible party (the

code that started the transaction in the first place) to end the transaction. This is

consistent with the behavior defined by JTA.

If concludeAuction() threw an exception, we must force the transaction to roll

back by calling tx.rollback(). This method either rolls back the transaction

immediately or marks the transaction for “rollback only” (if you’re using CMTs).

FAQ Is it faster to roll back read-only transactions? If code in a transaction reads

data but doesn’t modify it, should you roll back the transaction instead of

committing it? Would this be faster?

Apparently some developers found this approach to be faster in some

special circumstances, and this belief has now spread through the com￾munity. We tested this with the more popular database systems and

found no difference. We also failed to discover any source of real num￾bers showing a performance difference. There is also no reason why a

database system should be implemented suboptimally—that is, why it

shouldn’t use the fastest transaction cleanup algorithm internally. Always

commit your transaction and roll back if the commit fails.

It’s critically important to close the Session in a finally block in order to ensure that

the JDBC connection is released and returned to the connection pool. (This step

is the responsibility of the application, even in a managed environment.)

NOTE The example in listing 5.1 is the standard idiom for a Hibernate unit of

work; therefore, it includes all exception-handling code for the checked

HibernateException. As you can see, even rolling back a Transaction

and closing the Session can throw an exception. You don’t want to use this

example as a template in your own application, since you’d rather hide the

exception handling with generic infrastructure code. You can, for exam￾ple, use a utility class to convert the HibernateException to an unchecked

runtime exception and hide the details of rolling back a transaction and

Licensed to Jose Carlos Romero Figueroa <[email protected]>

160 CHAPTER 5

Transactions, concurrency, and caching

closing the session. We discuss this question of application design in more

detail in chapter 8, section 8.1, “Designing layered applications.”

However, there is one important aspect you must be aware of: the Ses￾sion has to be immediately closed and discarded (not reused) when an

exception occurs. Hibernate can’t retry failed transactions. This is no

problem in practice, because database exceptions are usually fatal (con￾straint violations, for example) and there is no well-defined state to con￾tinue after a failed transaction. An application in production shouldn’t

throw any database exceptions either.

We’ve noted that the call to commit() synchronizes the Session state with the data￾base. This is called flushing, a process you automatically trigger when you use the

Hibernate Transaction API.

5.1.3 Flushing the Session

The Hibernate Session implements transparent write behind. Changes to the domain

model made in the scope of a Session aren’t immediately propagated to the data￾base. This allows Hibernate to coalesce many changes into a minimal number of

database requests, helping minimize the impact of network latency.

For example, if a single property of an object is changed twice in the same

Transaction, Hibernate only needs to execute one SQL UPDATE. Another exam￾ple of the usefulness of transparent write behind is that Hibernate can take

advantage of the JDBC batch API when executing multiple UPDATE, INSERT, or

DELETE statements.

Hibernate flushes occur only at the following times:

■ When a Transaction is committed

■ Sometimes before a query is executed

■ When the application calls Session.flush() explicitly

Flushing the Session state to the database at the end of a database transaction is

required in order to make the changes durable and is the common case. Hibernate

doesn’t flush before every query. However, if there are changes held in memory that

would affect the results of the query, Hibernate will, by default, synchronize first.

You can control this behavior by explicitly setting the Hibernate FlushMode via a

call to session.setFlushMode(). The flush modes are as follows:

■ FlushMode.AUTO—The default. Enables the behavior just described.

■ FlushMode.COMMIT—Specifies that the session won’t be flushed before query

execution (it will be flushed only at the end of the database transaction). Be

Licensed to Jose Carlos Romero Figueroa <[email protected]>

Understanding database transactions 161

aware that this setting may expose you to stale data: modifications you made

to objects only in memory may conflict with the results of the query.

■ FlushMode.NEVER—Lets you specify that only explicit calls to flush() result

in synchronization of session state with the database.

We don’t recommend that you change this setting from the default. It’s provided

to allow performance optimization in rare cases. Likewise, most applications rarely

need to call flush() explicitly. This functionality is useful when you’re working

with triggers, mixing Hibernate with direct JDBC, or working with buggy JDBC driv￾ers. You should be aware of the option but not necessarily look out for use cases.

Now that you understand the basic usage of database transactions with the

Hibernate Transaction interface, let’s turn our attention more closely to the sub￾ject of concurrent data access.

It seems as though you shouldn’t have to care about transaction isolation—the

term implies that something either is or is not isolated. This is misleading. Complete

isolation of concurrent transactions is extremely expensive in terms of application

scalability, so databases provide several degrees of isolation. For most applications,

incomplete transaction isolation is acceptable. It’s important to understand the

degree of isolation you should choose for an application that uses Hibernate and

how Hibernate integrates with the transaction capabilities of the database.

5.1.4 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 imple￾ment 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 devel￾oper, is to understand the capabilities of your database and how to change the data￾base isolation behavior if needed in your particular scenario (and by your data

integrity requirements).

Tải ngay đi em, còn do dự, trời tối mất!