-
Language:
English
-
Language:
English
Red Hat Training
A Red Hat training course is available for Red Hat JBoss Web Server
10.6. Modifying Objects
10.6.1. Modifying Persistent Objects
Transactional persistent instances (i.e. objects loaded, saved, created or queried by the
Session
) can be manipulated by the application, and any changes to persistent state will be persisted when the Session
is flushed. This is discussed later in this chapter. There is no need to call a particular method (like update()
, which has a different purpose) to make your modifications persistent. The most straightforward way to update the state of an object is to load()
it and then manipulate it directly while the Session
is open:
DomesticCat cat = (DomesticCat) sess.load( Cat.class, new Long(69) ); cat.setName("PK"); sess.flush(); // changes to cat are automatically detected and persisted
Sometimes this programming model is inefficient, as it requires in the same session both an SQL
SELECT
to load an object and an SQL UPDATE
to persist its updated state. Hibernate offers an alternate approach by using detached instances.
Important
Hibernate does not offer its own API for direct execution of
UPDATE
or DELETE
statements. Hibernate is a state management service, you do not have to think in statements to use it. JDBC is a perfect API for executing SQL statements, you can get a JDBC Connection
at any time by calling session.connection()
. Furthermore, the notion of mass operations conflicts with object/relational mapping for online transaction processing-oriented applications. Future versions of Hibernate can, however, provide special mass operation functions.
10.6.2. Modifying Detached Objects
Many applications need to retrieve an object in one transaction, send it to the UI layer for manipulation, then save the changes in a new transaction. Applications that use this kind of approach in a high-concurrency environment usually use versioned data to ensure isolation for the "long" unit of work.
Hibernate supports this model by providing for reattachment of detached instances using the
Session.update()
or Session.merge()
methods:
// in the first session Cat cat = (Cat) firstSession.load(Cat.class, catId); Cat potentialMate = new Cat(); firstSession.save(potentialMate); // in a higher layer of the application cat.setMate(potentialMate); // later, in a new session secondSession.update(cat); // update cat secondSession.update(mate); // update mate
If the
Cat
with identifier catId
had already been loaded by secondSession
when the application tried to reattach it, an exception would have been thrown.
Use
update()
if you are certain that the session does not contain an already persistent instance with the same identifier. Use merge()
if you want to merge your modifications at any time without consideration of the state of the session. In other words, update()
is usually the first method you would call in a fresh session, ensuring that the reattachment of your detached instances is the first operation that is executed.
The application should individually
update()
detached instances that are reachable from the given detached instance only if it wants their state to be updated. This can be automated using transitive persistence. See Section 10.7.5, “Transitive Persistence” for further information.
The
lock()
method also allows an application to reassociate an object with a new session. However, the detached instance has to be unmodified.
//just reassociate: sess.lock(fritz, LockMode.NONE); //do a version check, then reassociate: sess.lock(izi, LockMode.READ); //do a version check, using SELECT ... FOR UPDATE, then reassociate: sess.lock(pk, LockMode.UPGRADE);
Note that
lock()
can be used with various LockMode
s. See the API documentation and the chapter on transaction handling for more information. Reattachment is not the only usecase for lock()
.
Other models for long units of work are discussed in the Optimistic Concurrency Control section: Section 11.4.1, “About Optimistic Concurrency Control”