Hibernate.orgCommunity Documentation
Table of Contents
        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
                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.
            
                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.
    
            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
        
Example 5.1. Example of making an entity persistent
// Using the Hibernate Session DomesticCat fritz = new DomesticCat(); fritz.setColor( Color.GINGER ); fritz.setSex( 'M' ); fritz.setName( "Fritz" ); session.save( fritz );
// Using the JPA EntityManager DomesticCat fritz = new DomesticCat(); fritz.setColor( Color.GINGER ); fritz.setSex( 'M' ); fritz.setName( "Fritz" ); entityManager.persist( fritz );
            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.
Example 5.3. Example of obtaining an entity reference without initializing its data
Book book = new Book(); book.setAuthor( session.byId( Author.class ).getReference( authorId ) );
Book book = new Book(); book.setAuthor( entityManager.getReference( Author.class, authorId ) );
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.
Example 5.4. Example of obtaining an entity reference with its data initialized
session.byId( Author.class ).load( authorId );
entityManager.find( Author.class, authorId );
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.
Example 5.5. Example of simple natural-id access
@Entity
public class User {
	@Id
	@GeneratedValue
	Long id;
	@NaturalId
	String userName;
	...
}
// use getReference() to create associations...
Resource aResource = (Resource) session.byId( Resource.class ).getReference( 123 );
User aUser = (User) session.bySimpleNaturalId( User.class ).getReference( "steve" );
aResource.assignTo( user );
// use load() to pull initialzed data
return session.bySimpleNaturalId( User.class ).load( "steve" );
        Example 5.6. Example of natural-id access
import java.lang.String;
@Entity
public class User {
	@Id
	@GeneratedValue
	Long id;
	@NaturalId
	String system;
	@NaturalId
	String userName;
	...
}
// use getReference() to create associations...
Resource aResource = (Resource) session.byId( Resource.class ).getReference( 123 );
User aUser = (User) session.byNaturalId( User.class )
		.using( "system", "prod" )
		.using( "userName", "steve" )
		.getReference();
aResource.assignTo( user );
// use load() to pull initialzed data
return session.byNaturalId( User.class )
		.using( "system", "prod" )
		.using( "userName", "steve" )
		.load();
        
            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:
getReferenceShould 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.
loadWill 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.
Example 5.7. Example of refreshing entity state
Cat cat = session.get( Cat.class, catId ); ... session.refresh( cat );
Cat cat = entityManager.find( Cat.class, catId ); ... entityManager.refresh( cat );
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 the discussion of non-identifier generated attributes in the
            Hibernate User Guide
        
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.
Example 5.8. Example of modifying managed state
Cat cat = session.get( Cat.class, catId ); cat.setName( "Garfield" ); session.flush(); // generally this is not explicitly needed
Cat cat = entityManager.find( Cat.class, catId ); cat.setName( "Garfield" ); entityManager.flush(); // generally this is not explicitly needed
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.
Reattachment is the process of taking an incoming entity instance that is in detached state and re-associating it with the current persistence context.
                    JPA does not provide for this model.  This is only available through Hibernate
                    org.hibernate.Session.
                
Example 5.9. Example of reattaching a detached entity
session.lock( someDetachedCat, LockMode.NONE );
session.saveOrUpdate( someDetachedCat );
                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.  Unless
                the entity is mapped with select-before-update, in which case 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.
            
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.
Example 5.10. Visualizing merge
Object detached = ...; Object managed = entityManager.find( detached.getClass(), detached.getId() ); managed.setXyz( detached.getXyz() ); ... return managed;
That is not exactly what happens, but its a good visualization.
Example 5.11. Example of merging a detached entity
Cat theManagedInstance = session.merge( someDetachedCat );
Cat theManagedInstance = entityManager.merge( someDetachedCat );
An application can verify the state of entities and collections in relation to the persistence context.
Example 5.12. Examples of verifying managed state
assert session.contains( cat );
assert entityManager.contains( cat );
Example 5.13. Examples of verifying laziness
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
}
            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
}
        
            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
        
Example 5.14. Alternative JPA means to verify laziness
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
}