Show Table of Contents
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
Sessionis 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
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
SELECTto load an object and an SQL
UPDATEto persist its updated state. Hibernate offers an alternate approach by using detached instances.
Hibernate does not offer its own API for direct execution of
DELETEstatements. 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
Connectionat 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
// 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
catIdhad already been loaded by
secondSessionwhen the application tried to reattach it, an exception would have been thrown.
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.
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);
lock()can be used with various
LockModes. See the API documentation and the chapter on transaction handling for more information. Reattachment is not the only usecase for
Other models for long units of work are discussed in the Optimistic Concurrency Control section: Section 11.4.1, “About Optimistic Concurrency Control”