[[pc]]
== Persistence Contexts
:sourcedir: ../../../../../test/java/org/hibernate/userguide/pc
:sourcedir-caching: ../../../../../test/java/org/hibernate/userguide/caching

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.

`transient`:: the entity has just been instantiated and is not associated with a persistence context.
It has no persistent representation in the database and typically no identifier value has been assigned (unless the _assigned_ generator was used).
`managed`, or `persistent`:: the entity has an associated identifier and is associated with a persistence context.
It may or may not physically exist in the database yet.
`detached`:: the entity has an associated identifier, but is no longer associated with a persistence context (usually because the persistence context was closed or the instance was evicted from the context)
`removed`:: the entity has an associated identifier and is associated with a persistence context, however it is scheduled for removal from the database.

Much of the `org.hibernate.Session` and `javax.persistence.EntityManager` methods deal with moving entities between these states.

[[pc-unwrap]]
=== Accessing Hibernate APIs from JPA

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

[[pc-unwrap-example]]
.Accessing Hibernate APIs from JPA
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-unwrap-example]
----
====

include::BytecodeEnhancement.adoc[]

[[pc-persist]]
=== Making entities persistent

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`.

[[pc-persist-jpa-example]]
.Making an entity persistent with JPA
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-persist-jpa-example]
----
====

[[pc-persist-native-example]]
.Making an entity persistent with Hibernate API
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-persist-native-example]
----
====

`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 `org.hibernate.Session` method to which the Hibernate `javax.persistence.EntityManager` implementation delegates.

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

[[pc-remove]]
=== Deleting (removing) entities

Entities can also be deleted.

[[pc-remove-jpa-example]]
.Deleting an entity with JPA
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-remove-jpa-example]
----
====

[[pc-remove-native-example]]
.Deleting an entity with Hibernate API
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-remove-native-example]
----
====

[NOTE]
====
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.
====

[[pc-get-reference]]
=== Obtain an entity reference without initializing its data

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.

[[pc-get-reference-jpa-example]]
.Obtaining an entity reference without initializing its data with JPA
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-get-reference-jpa-example]
----
====

[[pc-get-reference-native-example]]
.Obtaining an entity reference without initializing its data with Hibernate API
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-get-reference-native-example]
----
====

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

[[pc-find]]
=== Obtain an entity with its data initialized

It is also quite common to want to obtain an entity along with its data (e.g. like when we need to display it in the UI).

[[pc-find-jpa-example]]
.Obtaining an entity reference with its data initialized with JPA
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-find-jpa-example]
----
====

[[pc-find-native-example]]
.Obtaining an entity reference with its data initialized with Hibernate API
====

[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-find-native-example]
----
====

[[pc-find-by-id-native-example]]
.Obtaining an entity reference with its data initialized using the `byId()` Hibernate API
====

[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-find-by-id-native-example]
----
====

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

[[pc-find-natural-id]]
=== Obtain an entity by natural-id

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

[[pc-find-by-natural-id-entity-example]]
.Natural-id mapping
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-find-by-natural-id-entity-example]
----
====

We can also opt to fetch the entity or just retrieve a reference to it when using the natural identifier loading methods.

[[pc-find-by-simple-natural-id-example]]
.Get entity reference by simple natural-id
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-find-by-simple-natural-id-example]
----
====

[[pc-find-by-natural-id-example]]
.Load entity by natural-id
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-find-by-natural-id-example]
----
====

Hibernate offer a consistent API for accessing persistent data by identifier or by the natural-id. Each of these defines the same two 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.

Each of these two methods define an overloading variant accepting a `org.hibernate.LockOptions` argument.
Locking is discussed in a separate <<chapters/locking/Locking.adoc#locking,chapter>>.

[[pc-managed-state]]
=== Modifying managed/persistent state

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.

[[pc-managed-state-jpa-example]]
.Modifying managed state with JPA
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-managed-state-jpa-example]
----
====

[[pc-managed-state-native-example]]
.Modifying managed state with Hibernate API
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-managed-state-native-example]
----
====

[[pc-refresh]]
=== Refresh entity state

You can reload an entity instance and its collections at any time.

[[pc-refresh-jpa-example]]
.Refreshing entity state with JPA
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-refresh-jpa-example]
----
====

[[pc-refresh-native-example]]
.Refreshing entity state with Hibernate API
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-refresh-native-example]
----
====

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]
====
Only the entity instance and its value type 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 the discussion of non-identifier <<chapters/domain/basic_types.adoc#mapping-generated,generated attributes>>.
====

[[pc-refresh-gotchas]]
==== Refresh gotchas

The `refresh` entity state transition is meant to overwrite the entity attributes according to the info currently contained in the associated database record.

However, you have to be very careful when cascading the refresh action to any transient entity.

For instance, consider the following example:

[[pc-refresh-child-entity-jpa-example]]
.Refreshing entity state gotcha
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-refresh-child-entity-jpa-example]
----
====

In the aforementioned example, an `EntityNotFoundException` is thrown because the `Book` entity is still in a transient state.
When the refresh action is cascaded from the `Person` entity, Hibernate will not be able to locate the `Book` entity in the database.

For this reason, you should be very careful when mixing the refresh action with transient child entity objects.

[[pc-detach]]
=== Working with detached data

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 again.

[[pc-detach-reattach]]
==== Reattaching detached data

Reattachment is the process of taking an incoming entity instance that is in detached state and re-associating it with the current persistence context.

[IMPORTANT]
====
JPA does not provide for this model. This is only available through Hibernate `org.hibernate.Session`.
====

[[pc-detach-reattach-lock-example]]
.Reattaching a detached entity using `lock`
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-detach-reattach-lock-example]
----
====

[[pc-detach-reattach-saveOrUpdate-example]]
.Reattaching a detached entity using `saveOrUpdate`
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-detach-reattach-saveOrUpdate-example]
----
====

[NOTE]
====
The method name `update` is a bit misleading here.
It does not mean that an `SQL` `UPDATE` is immediately performed.
It does, however, mean that an `SQL` `UPDATE` will be performed when the persistence context is flushed since Hibernate does not know its previous state against which to compare for changes.
If the entity is mapped with `select-before-update`, Hibernate will pull the current state from the database and see if an update is needed.
====

Provided the entity is detached, `update` and `saveOrUpdate` operate exactly the same.

[[pc-merge]]
==== Merging detached data

Merging is the process of taking an incoming entity instance that is in detached state and copying its data over onto a new managed instance.

Although not exactly per se, the following example is a good visualization of the `merge` operation internals.

[[pc-merge-visualize-example]]
.Visualizing merge
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-merge-visualize-example]
----
====

[[pc-merge-jpa-example]]
.Merging a detached entity with JPA
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-merge-jpa-example]
----
====

[[pc-merge-native-example]]
.Merging a detached entity with Hibernate API
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-merge-native-example]
----
====

[[pc-contains]]
=== Checking persistent state

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

[[pc-contains-jpa-example]]
.Verifying managed state with JPA
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-contains-jpa-example]
----
====

[[pc-contains-native-example]]
.Verifying managed state with Hibernate API
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-contains-native-example]
----
====

[[pc-verify-lazy-jpa-example]]
.Verifying laziness with JPA
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-verify-lazy-jpa-example]
----
====

[[pc-verify-lazy-native-example]]
.Verifying laziness with Hibernate API
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-verify-lazy-native-example]
----
====

In JPA there is an alternative means to check laziness using the following `javax.persistence.PersistenceUtil` pattern (which is recommended wherever possible).

[[pc-verify-lazy-jpa-alternative-example]]
.Alternative JPA means to verify laziness
====
[source, JAVA, indent=0]
----
include::{sourcedir}/PersistenceContextTest.java[tags=pc-verify-lazy-jpa-alternative-example]
----
====

=== Evicting entities

When the `flush()` method is called, the state of the entity is synchronized with the database.
If you do not want this synchronization to occur, or if you are processing a huge number of objects and need to manage memory efficiently,
the `evict()` method can be used to remove the object and its collections from the first-level cache.

[[caching-management-jpa-detach-example]]
.Detaching an entity from the `EntityManager`
====
[source, JAVA, indent=0]
----
include::{sourcedir-caching}/FirstLevelCacheTest.java[tags=caching-management-jpa-detach-example]
----
====

[[caching-management-native-evict-example]]
.Evicting an entity from the Hibernate `Session`
====
[source, JAVA, indent=0]
----
include::{sourcedir-caching}/FirstLevelCacheTest.java[tags=caching-management-native-evict-example]
----
====

To detach all entities from the current persistence context, both the `EntityManager` and the Hibernate `Session` define a `clear()` method.

[[caching-management-clear-example]]
.Clearing the persistence context
====
[source, JAVA, indent=0]
----
include::{sourcedir-caching}/FirstLevelCacheTest.java[tags=caching-management-clear-example]
----
====

To verify if an entity instance is currently attached to the running persistence context, both the `EntityManager` and the Hibernate `Session` define a `contains(Object entity)` method.

[[caching-management-contains-example]]
.Verify if an entity is contained in a persistence context
====
[source, JAVA, indent=0]
----
include::{sourcedir-caching}/FirstLevelCacheTest.java[tags=caching-management-contains-example]
----
====
