Retrieving JPA Entity Objects

The Java Persistence API (JPA) provides various ways to retrieve objects from the database. The retrieval of objects does not require an active transaction because it does not change the content of the database.

The persistence context serves as a cache of retrieved entity objects. If a requested entity object is not found in the persistence context a new object is constructed and filled with data that is retrieved from the database (or from the L2 cache - if enabled). The new entity object is then added to the persistence context as a managed entity object and returned to the application.

Notice that construction of a new managed object during retrieval uses the no-arg constructor. Therefore, it is recommended to avoid unnecessary time consuming operations in no-arg constructors of entity classes and to keep them as simple as possible.

Retrieval by Class and Primary Key

Every entity object can be uniquely identified and retrieved by the combination of its class and its primary key. Given an EntityManagerjavax.persistence.EntityManager - JPA InterfaceInterface used to interact with the persistence context. em, the following code fragment demonstrates the retrieval of an Employee object whose primary key is 1:

  Employee employee = em.findEntityManager.find(entityClass,primaryKey) - JPA MethodFind by primary key.(Employee.class, 1);

Casting of the retrieved object to Employee is not required because findEntityManager.find(entityClass,primaryKey) - JPA MethodFind by primary key. is defined as returning an instance of the same class that it takes as a first argument (using generics).
An IllegalArgumentException is thrown if the specified class is not an entity class.

If the EntityManager already manages the specified entity object in its persistence context no retrieval is required and the existing managed object is returned as is. Otherwise, the object data is retrieved from the database and a new managed entity object with that retrieved data is constructed and returned. If the object is not found in the database null is returned.

A similar method, getReferenceEntityManager.getReference(entityClass,primaryKey) - JPA MethodGet an instance, whose state may be lazily fetched., can be considered the lazy version of find:

  Employee employee = em.getReferenceEntityManager.getReference(entityClass,primaryKey) - JPA MethodGet an instance, whose state may be lazily fetched.(Employee.class, 1);

The getReference method works like the find method except that if the entity object is not already managed by the EntityManager a hollow object might be returned (null is never returned). A hollow object is initialized with the valid primary key but all its other persistent fields are uninitialized. The object content is retrieved from the database and the persistent fields are initialized, lazily, when the entity object is first accessed. If the requested object does not exist an EntityNotFoundExceptionjavax.persistence.EntityNotFoundException - JPA ExceptionThrown by the persistence provider when an entity reference obtained by {@link EntityManager#getReference EntityManager.getReference} is accessed but the entity does not exist. is thrown when the object is first accessed.

The getReference method is useful when a reference to an entity object is required but not its content, such as when a reference to it has to be set from another entity object.

Retrieval by Eager Fetch

Retrieval of an entity object from the database might cause automatic retrieval of additional entity objects. By default, a retrieval operation is automatically cascaded through all the non collection and map persistent fields (i.e. through one-to-one and many-to-one relationships). Therefore, when an entity object is retrieved, all the entity objects that are reachable from it by navigation through non collection and map persistent fields are also retrieved. Theoretically, in some extreme situations this might cause the retrieval of the entire database into the memory, which is usually unacceptable.

A persistent reference field can be excluded from this automatic cascaded retrieval by using a lazy fetch type:

@Entityjavax.persistence.Entity - JPA AnnotationSpecifies that the class is an entity.
class Employee {
   :
  @ManyToOnejavax.persistence.ManyToOne - JPA AnnotationSpecifies a single-valued association to another entity class that
 has many-to-one multiplicity.(fetchjavax.persistence.ManyToOne.fetch - JPA Annotation Attribute(Optional) Whether the association should be lazily
 loaded or must be eagerly fetched.=FetchTypejavax.persistence.FetchType - JPA EnumDefines strategies for fetching data from the database..LAZYjavax.persistence.FetchType.LAZY - JPA Enum ConstantDefines that data can be lazily fetched.)
  private Employee manager;
   :
}

The default for non collection and map references is FetchTypejavax.persistence.FetchType - JPA EnumDefines strategies for fetching data from the database..EAGERjavax.persistence.FetchType.EAGER - JPA Enum ConstantDefines that data must be eagerly fetched., indicating that the retrieval operation is cascaded through the field. Explicitly specifying FetchTypejavax.persistence.FetchType - JPA EnumDefines strategies for fetching data from the database..LAZYjavax.persistence.FetchType.LAZY - JPA Enum ConstantDefines that data can be lazily fetched. in either @OneToOnejavax.persistence.OneToOne - JPA AnnotationSpecifies a single-valued association to another entity that has one-to-one multiplicity. or @ManyToOnejavax.persistence.ManyToOne - JPA AnnotationSpecifies a single-valued association to another entity class that has many-to-one multiplicity. annotations (currently ObjectDB does not distinguish between the two) excludes the field from participating in retrieval cascading.

When an entity object is retrieved all its persistent fields are initialized. A persistent reference field with the FetchType.LAZY fetch policy is initialized to reference a new managed hollow object (unless the referenced object is already managed by the EntityManager). In the example above, when an Employee instance is retrieved its manager field might reference a hollow Employee instance. In a hollow object the primary key is set but other persistent fields are uninitialized until the object fields are accessed.

On the other hand, the default fetch policy of persistent collection and map fields is FetchType.LAZY. Therefore, by default, when an entity object is retrieved any other entity objects that it references through its collection and map fields are not retrieved with it.

This can be changed by an explicit FetchType.EAGER setting:

@Entityjavax.persistence.Entity - JPA AnnotationSpecifies that the class is an entity.
class Employee {
   :
  @ManyToManyjavax.persistence.ManyToMany - JPA AnnotationSpecifies a many-valued association with many-to-many multiplicity.(fetchjavax.persistence.ManyToMany.fetch - JPA Annotation Attribute(Optional) Whether the association should be lazily loaded or
 must be eagerly fetched.=FetchTypejavax.persistence.FetchType - JPA EnumDefines strategies for fetching data from the database..EAGERjavax.persistence.FetchType.EAGER - JPA Enum ConstantDefines that data must be eagerly fetched.)
  private Collection<Project> projects;
   :
}

Specifying FetchTypejavax.persistence.FetchType - JPA EnumDefines strategies for fetching data from the database..EAGERjavax.persistence.FetchType.EAGER - JPA Enum ConstantDefines that data must be eagerly fetched. explicitly in @OneToManyjavax.persistence.OneToMany - JPA AnnotationSpecifies a many-valued association with one-to-many multiplicity. or @ManyToManyjavax.persistence.ManyToMany - JPA AnnotationSpecifies a many-valued association with many-to-many multiplicity. annotations (currently ObjectDB does not distinguish between the two) enables cascading retrieval for the field. In the above example, when an Employee instance is retrieved all the referenced Project instances are also retrieved automatically.

Retrieval by Navigation and Access

All the persistent fields of an entity object can be accessed freely, regardless of the current fetch policy, as long as the EntityManager is open. This also includes fields that reference entity objects that have not been loaded from the database yet and are represented by hollow objects. If the EntityManager is open when a hollow object is first accessed its content is automatically retrieved from the database and all its persistent fields are initialized.

From the point of view of the developer, it looks like the entire graph of objects is present in memory. This illusion, which is based on lazy transparent activation and retrieval of objects by ObjectDB, helps hide some of the direct interaction with the database and makes database programming easier.

For example, after retrieving an Employee instance from the database the manager field may include a hollow Employee entity object:

  Employee employee = em.findEntityManager.find(entityClass,primaryKey) - JPA MethodFind by primary key.(Employee.class, 1);
  Employee managed = employee.getManager(); // might be hollow

If manager is hollow transparent activation occurs when it is first accessed. For example:

  String managerName = manager.getName();

Accessing a persistent field in a hollow object (e.g. the name of the manager in the example above) causes the retrieval of missing content from the database and initialization of all the persistent fields.

As seen, the entire graph of objects is available for navigation, regardless of the fetch policy. The fetch policy, however, does affect performance. Eager retrieval might minimize the round trips to the database and improve performance, but unnecessary retrieval of entity objects that are not in use will decrease performance.

The fetch policy also affects objects that become detached (e.g. when the EntityManager is closed). Transparent activation is not supported for detached objects. Therefore, only content that has already been fetched from the database is available in objects that are detached.

JPA 2 introduces methods for checking if a specified entity object or a specified persistent field is loaded. For example:

  PersistenceUtiljavax.persistence.PersistenceUtil - JPA InterfaceUtility interface between the application and the persistence
 provider(s). util = Persistencejavax.persistence.Persistence - JPA ClassBootstrap class that is used to obtain an {@link EntityManagerFactory}
 in Java SE environments..getPersistenceUtilPersistence.getPersistenceUtil() - JPA Static MethodReturn the PersistenceUtil instance();
  boolean isObjectLoaded = util.isLoadedPersistenceUtil.isLoaded(entity) - JPA MethodDetermine the load state of an entity.(employee);
  boolean isFieldLoaded = util.isLoadedPersistenceUtil.isLoaded(entity,attributeName) - JPA MethodDetermine the load state of a given persistent attribute.(employee, "address");

As shown above, a PersistenceUtiljavax.persistence.PersistenceUtil - JPA InterfaceUtility interface between the application and the persistence provider(s). instance is obtained from the static getPersistenceUtilPersistence.getPersistenceUtil() - JPA Static MethodReturn the PersistenceUtil instance method. It provides two isLoaded methods - one for checking an entity object and the other for checking a persistent field of an entity object.

Retrieval by Query

The most flexible method for retrieving objects from the database is to use queries. The official query language of JPA is JPQL (Java Persistence Query Language). It enables retrieval of objects from the database by using simple queries as well as complex, sophisticated ones. JPA queries and JPQL are described in chapter 4.

Retrieval by Refresh

Managed objects can be reloaded from the database by using the refreshEntityManager.refresh(entity) - JPA MethodRefresh the state of the instance from the database, overwriting changes made to the entity, if any. method:

  em.refreshEntityManager.refresh(entity) - JPA MethodRefresh the state of the instance from the database,
 overwriting changes made to the entity, if any.(employee);

The content of the managed object in memory is discarded (including changes, if any) and replaced by data that is retrieved from the database. This might be useful to ensure that the application deals with the most up to date version of an entity object, just in case it might have been changed by another EntityManager since it was retrieved.

An IllegalArgumentException is thrown by refresh if the argument is not a managed entity (including entity objects in the New, Removed or Detached states). If the object does not exist in the database anymore an EntityNotFoundExceptionjavax.persistence.EntityNotFoundException - JPA ExceptionThrown by the persistence provider when an entity reference obtained by {@link EntityManager#getReference EntityManager.getReference} is accessed but the entity does not exist. is thrown.

Cascading Refresh

Marking a reference field with CascadeTypejavax.persistence.CascadeType - JPA EnumDefines the set of cascadable operations that are propagated to the associated entity..REFRESHjavax.persistence.CascadeType.REFRESH - JPA Enum ConstantCascade refresh operation (or CascadeTypejavax.persistence.CascadeType - JPA EnumDefines the set of cascadable operations that are propagated to the associated entity..ALLjavax.persistence.CascadeType.ALL - JPA Enum ConstantCascade all operations, which includes REFRESHjavax.persistence.CascadeType.REFRESH - JPA Enum ConstantCascade refresh operation) indicates that refreshEntityManager.refresh(entity) - JPA MethodRefresh the state of the instance from the database, overwriting changes made to the entity, if any. operations should be cascaded automatically to entity objects that are referenced by that field (multiple entity objects can be referenced by a collection field):

@Entityjavax.persistence.Entity - JPA AnnotationSpecifies that the class is an entity.
class Employee {
     :
    @OneToOnejavax.persistence.OneToOne - JPA AnnotationSpecifies a single-valued association to another entity that has
 one-to-one multiplicity.(cascadejavax.persistence.OneToOne.cascade - JPA Annotation Attribute(Optional) The operations that must be cascaded to
 the target of the association.=CascadeTypejavax.persistence.CascadeType - JPA EnumDefines the set of cascadable operations that are propagated
 to the associated entity..REFRESHjavax.persistence.CascadeType.REFRESH - JPA Enum ConstantCascade refresh operation)
    private Address address;
     :
}

In the example above, the Employee entity class contains an address field that references an instance of Address, which is another entity class. Due to the CascadeType.REFRESH setting, when an Employee instance is refreshed the operation is automatically cascaded to the referenced Address instance, which is then automatically refreshed as well. Cascading may continue recursively when applicable (e.g. to entity objects that the Address object references, if any).