|
Hibernate example source code file (Persistence_Context.xml)
This example Hibernate source code file (Persistence_Context.xml) is included in the DevDaily.com
"Java Source Code
Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.
The Hibernate Persistence_Context.xml source code
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "Hibernate_Development_Guide.ent">
%BOOK_ENTITIES;
]>
<chapter>
<title>Persistence Contexts
<para>
Both the <interfacename>org.hibernate.Session API and
<interfacename>javax.persistence.EntityManager API represent a context for dealing with
persistent data. This concept is called a <literal>persistence context. Persistent data has a
state in relation to both a persistence context and the underlying database.
</para>
<itemizedlist>
<title>Entity states
<listitem>
<para>
<literal>new, or transient - the entity has just been instantiated and is
not associated with a persistence context. It has no persistent representation in the database and no
identifier value has been assigned.
</para>
</listitem>
<listitem>
<para>
<literal>managed, or persistent - the entity has an associated identifier
and is associated with a persistence context.
</para>
</listitem>
<listitem>
<para>
<literal>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)
</para>
</listitem>
<listitem>
<para>
<literal>removed - the entity has an associated identifier and is associated with a persistence
context, however it is scheduled for removal from the database.
</para>
</listitem>
</itemizedlist>
<!-- todo : need a "see also" link to cascading chapter -->
<para>
In Hibernate native APIs, the persistence context is defined as the
<interfacename>org.hibernate.Session. In JPA, the persistence context is defined by
<interfacename>javax.persistence.EntityManager. Much of the
<interfacename>org.hibernate.Session and
<interfacename>javax.persistence.EntityManager methods deal with moving entities between these
states.
</para>
<section>
<title>Making entities persistent
<para>
Once you've created a new entity instance (using the standard <literal>new operator) it is in
<literal>new state. You can make it persistent by associating it to either a
<interfacename>org.hibernate.Session or
<interfacename>javax.persistence.EntityManager
</para>
<example>
<title>Example of making an entity persistent
<programlisting>
<![CDATA[DomesticCat fritz = new DomesticCat();
fritz.setColor(Color.GINGER);
fritz.setSex('M');
fritz.setName("Fritz");
session.save(fritz);]]>
</programlisting>
<programlisting>
<![CDATA[DomesticCat fritz = new DomesticCat();
fritz.setColor(Color.GINGER);
fritz.setSex('M');
fritz.setName("Fritz");
entityManager.persist(fritz);]]>
</programlisting>
</example>
<sidebar>
<para>
<interfacename>org.hibernate.Session also has a method named persist
which follows the exact semantic defined in the JPA specification for the <methodname>persist
method. It is this method on <interfacename>org.hibernate.Session to which the
Hibernate <interfacename>javax.persistence.EntityManager implementation delegates.
</para>
</sidebar>
<para>
If the <classname>DomesticCat entity type has a generated identifier, the value is associated
to the instance when the <methodname>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 <methodname>save or persist is called.
</para>
</section>
<section>
<title>Deleting entities
<para>
Entities can also be deleted.
</para>
<example>
<title>Example of deleting an entity
<programlisting>
<![CDATA[session.delete( anAuthor );]]>
</programlisting>
<programlisting>
<![CDATA[entityManager.remove( anAuthor );]]>
</programlisting>
</example>
<para>
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
<interfacename>org.hibernate.Session delete method can be either
in managed or detached state, while the entity instance passed to <methodname>remove on
<interfacename>javax.persistence.EntityManager must be in managed state.
</para>
</section>
<section>
<title>Obtain an entity reference without initializing its data
<para>
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.
</para>
<example>
<title>Example of obtaining an entity reference without initializing its data
<programlisting>
<![CDATA[Book book = new Book();
book.setAuthor( session.load( Author.class, authorId ) );]]>
</programlisting>
<programlisting>
<![CDATA[Book book = new Book();
book.setAuthor( entityManager.getReference( Author.class, authorId ) );]]>
</programlisting>
</example>
<para>
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 <xref linkend="devguide-mappingEntities"/>. 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.
</para>
</section>
<section>
<title>Obtain an entity with its data initialized
<para>
It is also quite common to want to obtain an entity along with with its data, for display for example.
</para>
<example>
<title>Example of obtaining an entity reference with its data initialized
<programlisting>
<![CDATA[return session.get( Author.class, authorId );]]>
</programlisting>
<programlisting>
<![CDATA[return entityManager.find( Author.class, authorId );]]>
</programlisting>
</example>
<para>
In both cases null is returned if no matching database row was found.
</para>
</section>
<section>
<title>Refresh entity state
<para>
You can reload an entity instance and it's collections at any time.
</para>
<example>
<title>Example of refreshing entity state
<programlisting>
<![CDATA[Cat cat = session.get( Cat.class, catId );
...
session.refresh( cat );]]>
</programlisting>
<programlisting>
<![CDATA[Cat cat = entityManager.find( Cat.class, catId );
...
entityManager.refresh( cat );]]>
</programlisting>
</example>
<para>
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.
</para>
<para>
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 <literal>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 <xref linkend="devguide-mappingEntities"/> for information.
</para>
</section>
<section>
<title>Modifying managed/persistent state
<para>
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.
</para>
<example>
<title>Example of modifying managed state
<programlisting>
<![CDATA[Cat cat = session.get( Cat.class, catId );
cat.setName( "Garfield" );
session.flush(); // generally this is not explicitly needed]]>
</programlisting>
<programlisting>
<![CDATA[Cat cat = entityManager.find( Cat.class, catId );
cat.setName( "Garfield" );
entityManager.flush(); // generally this is not explicitly needed]]>
</programlisting>
</example>
</section>
<section>
<title>Working with detached data
<para>
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).
</para>
<para>
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.
</para>
<section>
<title>Reattaching detached data
<para>
Reattachment is the process of taking an incoming entity instance that is in detached state
and re-associating it with the current persistence context.
</para>
<important>
<para>
JPA does not provide for this model. This is only available through Hibernate
<interfacename>org.hibernate.Session.
</para>
</important>
<example>
<title>Example of reattaching a detached entity
<programlisting>
<![CDATA[session.update( someDetachedCat );]]>
</programlisting>
<programlisting>
<![CDATA[session.saveOrUpdate( someDetachedCat );]]>
</programlisting>
</example>
<para>
The method name <methodname>update is a bit misleading here. It does not mean that an
<literal>SQL UPDATE is immediately performed. It does, however, mean that an
<literal>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.
</para>
<para>
Provided the entity is detached, <methodname>update and saveOrUpdate
operate exactly the same.
</para>
</section>
<section>
<title>Merging detached data
<para>
Merging is the process of taking an incoming entity instance that is in detached state and copying its
data over onto a new instance that is in managed state.
</para>
<example>
<title>Visualizing merge
<programlisting>
<![CDATA[Object detached = ...;
Object managed = entityManager.find( detached.getClass(), detached.getId() );
managed.setXyz( detached.getXyz() );
...
return managed;]]>
</programlisting>
</example>
<para>
That is not exactly what happens, but its a good visualization.
</para>
<example>
<title>Example of merging a detached entity
<programlisting>
<![CDATA[Cat theManagedInstance = session.merge( someDetachedCat );]]>
</programlisting>
<programlisting>
<![CDATA[Cat theManagedInstance = entityManager.merge( someDetachedCat );]]>
</programlisting>
</example>
</section>
</section>
<section>
<title>Checking persistent state
<para>
An application can verify the state of entities and collections in relation to the persistence context.
</para>
<example>
<title>Examples of verifying managed state
<programlisting>
<programlisting>
</example>
<example>
<title>Examples of verifying laziness
<programlisting>
<![CDATA[if ( Hibernate.isInitialized( customer.getAddress() ) {
//display address if loaded
}
if ( Hibernate.isInitialized( customer.getOrders ) ) {
//display orders if loaded
}
if (Hibernate.isPropertyInitialized(customer, "detailedBio") ) {
//display property detailedBio if loaded
}]]>
</programlisting>
<programlisting>
<![CDATA[javax.persistence.PersistenceUnitUtil jpaUtil = entityManager.getEntityManagerFactory().getPersistenceUnitUtil();
if ( jpaUtil.isLoaded( customer.getAddress() ) {
//display address if loaded
}
if ( jpaUtil.isLoaded( customer.getOrders ) ) {
//display orders if loaded
}
if (jpaUtil.isLoaded(customer, "detailedBio") ) {
//display property detailedBio if loaded
}]]>
</programlisting>
</example>
<para>
In JPA there is an alternative means to check laziness using the following
<interfacename>javax.persistence.PersistenceUtil pattern. However, the
<interfacename>javax.persistence.PersistenceUnitUtil is recommended where ever possible
</para>
<example>
<title>Alternative JPA means to verify laziness
<programlisting>
<![CDATA[javax.persistence.PersistenceUtil jpaUtil = javax.persistence.Persistence.getPersistenceUtil();
if ( jpaUtil.isLoaded( customer.getAddress() ) {
//display address if loaded
}
if ( jpaUtil.isLoaded( customer.getOrders ) ) {
//display orders if loaded
}
if (jpaUtil.isLoaded(customer, "detailedBio") ) {
//display property detailedBio if loaded
}]]>
</programlisting>
</example>
</section>
<section>
<title>Accessing Hibernate APIs from JPA
<para>
JPA defines an incredibly useful method to allow applications access to the APIs of the underlying provider.
</para>
<example>
<title>Usage of EntityManager.unwrap
<programlisting>
<![CDATA[Session session = entityManager.unwrap( Session.class );
SessionImplementor sessionImplementor = entityManager.unwrap( SessionImplementor.class );]]>
</programlisting>
</example>
</section>
</chapter>
Other Hibernate examples (source code examples)
Here is a short list of links related to this Hibernate Persistence_Context.xml source code file:
|