Wednesday, August 27, 2008

Detached object in Hibernate

Hibernate defines and supports the following object states:

  • Transient - an object is transient if it has just been instantiated using the new operator, and it is not associated with a Hibernate Session. It has no persistent representation in the database and no identifier value has been assigned. Transient instances will be destroyed by the garbage collector if the application doesn't hold a reference anymore. Use the Hibernate Session to make an object persistent (and let Hibernate take care of the SQL statements that need to be executed for this transition).

  • Persistent - a persistent instance has a representation in the database and an identifier value. It might just have been saved or loaded, however, it is by definition in the scope of a Session. Hibernate will detect any changes made to an object in persistent state and synchronize the state with the database when the unit of work completes. Developers don't execute manual UPDATE statements, or DELETE statements when an object should be made transient.

  • Detached - a detached instance is an object that has been persistent, but its Session has been closed. The reference to the object is still valid, of course, and the detached instance might even be modified in this state. A detached instance can be reattached to a new Session at a later point in time, making it (and all the modifications) persistent again. This feature enables a programming model for long running units of work that require user think-time. We call them application transactions, i.e. a unit of work from the point of view of the user.

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.

Usually update() or saveOrUpdate() are used in the following scenario:

  • the application loads an object in the first session

  • the object is passed up to the UI tier

  • some modifications are made to the object

  • the object is passed back down to the business logic tier

  • the application persists these modifications by calling update() in a second session

saveOrUpdate() does the following:

  • if the object is already persistent in this session, do nothing

  • if another object associated with the session has the same identifier, throw an exception

  • if the object has no identifier property, save() it

  • if the object's identifier has the value assigned to a newly instantiated object, save() it

  • if the object is versioned (by a or ), and the version property value is the same value assigned to a newly instantiated object, save() it

  • otherwise update() the object

and merge() is very different:

  • if there is a persistent instance with the same identifier currently associated with the session, copy the state of the given object onto the persistent instance

  • if there is no persistent instance currently associated with the session, try to load it from the database, or create a new persistent instance

  • the persistent instance is returned

  • the given instance does not become associated with the session, it remains detached

No comments:

Post a Comment