alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

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.

Java - Hibernate tags/keywords

apis, cdata, cdata, entities, fritz, hibernate, hibernate, in, it, it, jpa, jpa, the, you

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:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.