Hibernate.orgCommunity Documentation

Chapter 3. Persistence Contexts

Table of Contents

3.1. Making entities persistent
3.2. Deleting entities
3.3. Obtain an entity reference without initializing its data
3.4. Obtain an entity with its data initialized
3.5. Obtain an entity by natural-id
3.6. Refresh entity state
3.7. Modifying managed/persistent state
3.8. Working with detached data
3.8.1. Reattaching detached data
3.8.2. Merging detached data
3.9. Checking persistent state
3.10. Accessing Hibernate APIs from JPA

Both the org.hibernate.Session API and javax.persistence.EntityManager API represent a context for dealing with persistent data. This concept is called a persistence context. Persistent data has a state in relation to both a persistence context and the underlying database.

Entity states

In Hibernate native APIs, the persistence context is defined as the org.hibernate.Session. In JPA, the persistence context is defined by javax.persistence.EntityManager. Much of the org.hibernate.Session and javax.persistence.EntityManager methods deal with moving entities between these states.

Once you've created a new entity instance (using the standard new operator) it is in new state. You can make it persistent by associating it to either a org.hibernate.Session or javax.persistence.EntityManager


org.hibernate.Session also has a method named persist which follows the exact semantic defined in the JPA specification for the persist method. It is this method on org.hibernate.Session to which the Hibernate javax.persistence.EntityManager implementation delegates.

If the DomesticCat entity type has a generated identifier, the value is associated to the instance when the save or persist is called. If the identifier is not automatically generated, the application-assigned (usually natural) key value has to be set on the instance before save or persist is called.

Entities can also be deleted.


It is important to note that Hibernate itself can handle deleting detached state. JPA, however, disallows it. The implication here is that the entity instance passed to the org.hibernate.Session delete method can be either in managed or detached state, while the entity instance passed to remove on javax.persistence.EntityManager must be in managed state.

Sometimes referred to as lazy loading, the ability to obtain a reference to an entity without having to load its data is hugely important. The most common case being the need to create an association between an entity and another, existing entity.


The above works on the assumption that the entity is defined to allow lazy loading, generally through use of runtime proxies. For more information see ???. In both cases an exception will be thrown later if the given entity does not refer to actual database state if and when the application attempts to use the returned proxy in any way that requires access to its data.

It is also quite common to want to obtain an entity along with with its data, for display for example.


In both cases null is returned if no matching database row was found.

In addition to allowing to load by identifier, Hibernate allows applications to load by declared natural identifier.



Just like we saw above, access entity data by natural id allows both the load and getReference forms, with the same semantics.

Accessing persistent data by identifier and by natural-id is consistent in the Hibernate API. Each defines the same 2 data access methods:

getReference

Should be used in cases where the identifier is assumed to exist, where non-existence would be an actual error. Should never be used to test existence. That is because this method will prefer to create and return a proxy if the data is not already associated with the Session rather than hit the database. The quintessential use-case for using this method is to create foreign-key based associations.

load

Will return the persistent data associated with the given identifier value or null if that identifier does not exist.

In addition to those 2 methods, each also defines the method with accepting a org.hibernate.LockOptions argument. Locking is discussed in a separate chapter.

You can reload an entity instance and it's collections at any time.


One case where this is useful is when it is known that the database state has changed since the data was read. Refreshing allows the current database state to be pulled into the entity instance and the persistence context.

Another case where this might be useful is when database triggers are used to initialize some of the properties of the entity. Note that only the entity instance and its collections are refreshed unless you specify REFRESH as a cascade style of any associations. However, please note that Hibernate has the capability to handle this automatically through its notion of generated properties. See ??? for information.

Entities in managed/persistent state may be manipulated by the application and any changes will be automatically detected and persisted when the persistence context is flushed. There is no need to call a particular method to make your modifications persistent.


Detachment is the process of working with data outside the scope of any persistence context. Data becomes detached in a number of ways. Once the persistence context is closed, all data that was associated with it becomes detached. Clearing the persistence context has the same effect. Evicting a particular entity from the persistence context makes it detached. And finally, serialization will make the deserialized form be detached (the original instance is still managed).

Detached data can still be manipulated, however the persistence context will no longer automatically know about these modification and the application will need to intervene to make the changes persistent.

An application can verify the state of entities and collections in relation to the persistence context.



In JPA there is an alternative means to check laziness using the following javax.persistence.PersistenceUtil pattern. However, the javax.persistence.PersistenceUnitUtil is recommended where ever possible


JPA defines an incredibly useful method to allow applications access to the APIs of the underlying provider.