In this article we will review Java Persistence EntityManager Operations for those who are looking to do the Component Developer Exam. We will first focus on the EntityManager and the EntityManager API before we dive into the entity instance lifecycle and look at callback methods associated with an entity lifecycle. Finally we will update our Tudo List application that we continued building in the previous article, Tutorial: In Depth Review of Entities for the Component Developer Exam.

What is the Entity Manager

One of the key principles that guided the development of the EJB3 specification was to limit the requirement of an EJB3 container to areas that it would actually add value to the development of enterprise applications. It is within this context, that the developers of the specification came up an abstraction that would be flexible enough to be used outside of the EJB3 container as well as available for use with both TopLink or Hibernate persistence frameworks. It is from this that the persistence model, the Java Persistence API was born. The most important part of the API is most likely the EntityManager API because you use it to manage the lifecycle of entities in an application. The EntityManger is the key object for all persistence operations. As entities are basically POJOs it is only through itís interaction with the EntityManager that they become persistent. The EntityManger also handles all the object-relational mapping between your entity classes and the relational database. The EntityManager API also provides the means for creating queries, finding entities, synchronizing, and inserting entities into the database. Finally it provides caching and manages the interaction between an entity and the transactional services used. If the entity manager is container-managed, then it will normally use JTA (Java Transaction API) transactions and while if it is application managed, it can use JTA transactions but normally is will use resource-local transactions. For the later, there is an API, the EntityTransaction interface that provides methods for beginning, committing and rolling back of resource-local transactions.

Tutorial: Review of JPA EntityManager Operations for the Component Developer Exam-a6-entitymanager.jpg
Figure: Entity Managerís Role in Object/Relational Mapping

Using the EntityManager API

The entity manager provide the bridge between the relational and object worlds. Anytime that you want to create an entity, it is the EntityManager that transforms the entity into a new database record. Conversely if you want to instantiate an entity, the EntityManager will create the entity and populate it with the relevant relational data. Also if you want to update or delete an entity, the EntityManager will locate the relational record and either update it or delete it.

Beyond providing CRUD functionality, the EntityManager keeps entities synched with the database automatically as long as they are not detached from the EntityManager. The EntityManager provides the most important interface in JPA and is engine for most of the ORM functionality in the API. This is despite being a rather small and intuitive interface compared to many Java APIs. Below is a list of the most commonly used operations by the EntityManager interface

Tutorial: Review of JPA EntityManager Operations for the Component Developer Exam-a6-entitymanageroperations.jpg
Table: Most Commonly Used EntityManager Interface Operations

Entity Manager Operations

Outside of the CRUD operations that were mentioned in the previous paragraph, there are a number of operations that I will detail from the list above. But first I will start with ensuring that you understand the most basic operations of persisting entities.

Persist Operations

The purpose of the persist method is to create new entity record in the database. It is not used for updating existing records. In this case, you need to ensure that if the primary keys or identity are being provided manually and not generated automatically, that the identity or primary key of the entity being persisted doesnít exist in the database. An example is provided below:

Java Code: Example of persist operation
public void saveTodo(Todo todo) {
   em.persist(todo);
}
Note that if the data violates the databaseís integrity constraints, the persistence provider will throw a javax.persistence.PersistenceException. This is wrapped into a database exception. Also in transaction-scoped EntityManagers, the INSERT statement that is associated with this record will generally be issued when the enclosing transaction is about to commit. For the example above from the Tudo List application, this means the SQL statements are issued when the saveTodo method returns. If the EntityManager is application-managed, the INSERT statement will most likely be issued just before the EntityManager is closed. It is also possible that the INSERT statement can be issued at a point when the EntityManager is being flushed. What is important to remember is that the database operation can be done by either yourself or the EntityManager without waiting until the end of the transaction or the close of the EntityManager. If the database update is not wrapped in a transaction context when the persist method is invoked, a TransactionRequiredException will be thrown for a transaction-scoped entity manager. For application-managed or extended entity manager, instead, the persist method will attach the entity to a persistence context and when a new transaction starts, the entity manager will join the transaction and save the changes when that transaction commits. The same process will occur for other EntityManager methodís (i.e. refresh, merge, remove and flush) as well.

One thing that is not noticed in the example above with the persisting of the Todo operation is that it has relationships to other entities. This is shown below:

Java Code: Todo Class
@Entity
@Table(name = "TODO")
public class Todo implements Serializable, Comparable<Todo> {
   ...
   private Integer todoId;
   private TodoList todoList;
   ...
   @Id
   @Column(name="id")
   @GeneratedValue
   public Integer getTodoId() {
       return todoId;
   }
   ...
   @ManyToOne 
   @JoinColumn(name="ID", referencedColumnName="ID")
   public TodoList getTodoList() {
       return todoList;
   }
}
Notice that is has a many-to-one relationship with the TodoList entity. In this case, the saveTodo method just retrieves the TodoList entity and ensures it is already managed. It can then ensure that any changes are transparently synchronized. If in the case in the TodoList entity related to the Todo we are persisting does not yet exist in the database. This does not happen very often for one-to-many and many-to-many relationships. In such cases, the related entity is more than likely already saved in the database. However, it does occur a lot more often for one-to-one relationships. In this case we would need to manually create the TodoList entity before we could persist the Todo. Fortunately as a TodoList cannot be set for the Todo without being fetched or created, this has already been done elsewhere in the application before we invoke the saveTodo. If it wasnít we would have to do something like the following:

Java Code: Example of persist operation with multiple entities
 public Todo saveTodo(Description desc, int priority, Date creationDate, Date dueDate,
   Date completionData, boolean completed,  String tdname, boolean rssAllowed,
   Date lastUpdate, String login, String firstName, String lastName, String email) { 
   User user = new User(); 
   user.setLogin(login); 
   user.setEmail(email);
   user.setFirstName(firstName);
   user.setLastName(lastName);
   TodoList todoList = new TodoList(); 
   todoList.setName(tdname); 
   todoList.setRssAllowed(rssAllowed); 
   todoList.setLastUpdate(lastUpdate);
   HashSet set = new HashSet<User>(user);
   todoList.setUsers(set);
   Todo todo = new Todo();
   todo.setCompleted(completed);
   todo.setDescription(desc);
   todo.setCreationDate(creationDate);
   todo.setDueDate(dueDate);
   todo.setPriority(priority);
   todo.setTodoList(todoList);
   entityManager.persist(todo);
   return todo;;
}
Persisting Operations with Cascade

The default behavior for persisting related entities is not to perform a cascade. So by default, the User and TodoList will not be persisted and would not be included in the INSERT statement generated for persisting the Todo entity that is shown in the listing above. In order to do this, it is necessary to add the following to the Todo entity declaration:

Java Code: Defining the CascadeType
public class Todo {
@OneToOne(cascade=CascadeType.PERSIST) 
public void setTodoList(TodoList todoList) {
The cascade element in the @OneToOne annotation is similar to cascading in the database. Cascading in ORM-based persistence is similar to the idea of cascading in data- bases. The cascade element tells the EntityManager how to propagate the persistence operation on a particular entity into entities related to it. The default for the cascade element is for no persistence operations to be propagated to related entities. But you can set the cascade element to ALL, MERGE, PERSIST, REFRESH, or REMOVE. The table below shows the proper values:

Tutorial: Review of JPA EntityManager Operations for the Component Developer Exam-a6-cascadetypes.jpg
Table: CascadeType Values

Since we have set the CascadeType to PERSIST for the Todo Entity, the EntityManager will determine that the TodoList is associated with the Todo and that it must be persisted as well. Note that also this needs to be done in the TodoList for the User entity as well so that the User will be persisted as well. This would also work if we set the CascadeType to ALL. For all the other values, the persist operation would not be propagated for the TodoList.

Retrieve Operations

The EntityManager has a several ways to retrieve entity instances from the database. The simplest way of retrieving an entity is by its primary key using the find method . The other ways all involve using the query API and JPQL. An example of the find method is shown below:

Java Code: Example of retrieve operation
public Todo getTodo(Integer todoId) {
        Todo todo = (Todo) em.find(Todo.class, todoId);
        if (todo == null) {
            throw new NoResultException("Unable to find todo: " + todoId);
        }
        return todo;
}
The find method has two parameters. The first parameter specifies the Java type of the entity to be retrieved and the second parameter specifies the identity value for the entity instance to retrieve. As an entity identity can either be a simple Java type identified by the @Id annotation or a composite primary key class specified through the @EmbeddedId or @IdClass annotation, the find method is passed a simple java.lang.Long value matching the Todo entityís @Id annotated identity, todoId.

The find method supports composite primary keys as well. The identity can be encapsulated in a composite primary key class annotated with the @IdClass annotation. An example of this is shown below:

Java Code: Example of find operation
FlightPK flightKey = new FlightPK();
flightKey.setFlightName(flightName); 
flightKey.setFlightNumber(flightNumber);
Flight flight = entityManager.find(Flight.class, flightKey);
The find method inspects the details of the entity class passed as the first parameter and generates a SELECT statement to retrieve the entity data. This SELECT statement that is generated uses the second parameter of the find method to populate the primary key values. If there is no matching entity in the database, the find method will not throw any exceptions but instead, the EntityManager will return null or an empty entity and it is the responsibility of your application to handle this situation. This was done in the listing above for the getTodo method. It is not necessary to call the find method in a transactional con- text. However, the retrieved entity will be detached unless there is a transaction context so it is best to call the find method from within a transaction. An important feature of the find method is the utilization of EntityManager caching. If the persistence provider supports caching and the entity is already cached, then the EntityManager will return a cached instance of the entity. Otherwise it will retrieve it from the database. As the two main persistence frameworks, Hibernate and TopLink support caching, it is highly likely that you have access to this feature.

Another key optimization feature of JPA is the option of lazy and eager loading. When the generated SELECT statement for the getTodo method will attempt to retrieve all of the entity field data when the find method is invoked. This is the default behavior for JPA. In many cases for reasons of performance, this is not preferred behavior. Fetch modes allow us to modify how objects are retrieved in order to optimize application performance. There are basically to fetch modes that are of interest:
  • Eager Fetching - loads all entity instance data when an entity is retrieved from the database
  • Lazy Fetching - loads entity instance data cautiously and only as needed from the database


If you are loading large binary objects (BLOBs), such as pictures. It causes a significant performance hit to load a picture as part of an entity especially if it is used in a lot of places in the application. This is because loading BLOB data is typically a long-running, I/O-heavy operations. In this case, we use an optimization strategy known as lazy fetching.
JPA has a number of mechanisms to support lazy fetching. Using the @Basic annotation to specify the column fetch-mode is the most straight forward mechanism. For example, if in a online retail site, we wanted to use lazy fetching for the picture property on the Product or SKU entity it would be done in the following manner:

Java Code: Definition of fetch type
@Column(name="PICTURE") 
@Lob 
@Basic(fetch=FetchType.LAZY) 
public byte[] getPicture() {
   return picture;
}
In this case, the picture data would be automatically loaded from the database when the property is first accessed through the getPicture method. Note that the EntityManager will issue an additional SELECT statement in order to retrieve the picture data when the lazily loaded field is first accessed. You could run into a situation where all entity data in an application is lazily loaded. This would flood the database with a large number of minor SELECT statements (accessing one column possibly) as entity data is accessed.

Finding and Loading Related Entities
Lazy loading is often used to control the retrieval of related entities. The EntityManagerís find method must retrieve all entities related to the one returned by the method. So when used in the getTodo method, the EntityManager will not only fetch the Todo but the TodoList as well as the User entity. Note that the TodoList has a many-to-one relationship with the Todo entities as well as many-to-many User entities since the TodoList are shared. Finally the User also can have several roles so there is another many-to-many relationship between the User and Role entities. This is shown in the figure below:

Tutorial: Review of JPA EntityManager Operations for the Component Developer Exam-a6-todolistdomain.jpg
Figure: The relationships between Todo, TodoList, User and Role Entities

The find method when invoked will return an instance of an Todo as well as automatically retrieving the TodoList, User, and Role entities associated with the instance and populates them into their respective Item entity properties. All these relationship annotations include @ManyToOne, @OneToMany, and @ManyToMany annotations would need to have a fetch element to control fetch modes just like the @Basic annotation discussed in the previous section. Since at present, none of the relationship annotations are specified in the fetch element, the default for each annotation takes effect. The TodoList entity is shown below:

Java Code: TodoList class
@Entity
@Table(name = "TODO_LIST")
public class TodoList implements Serializable, Comparable<TodoList> {
   ...
    private Integer listId;
    private String name;
    private Set<Todo> todos;    
    private Set<User> users;
   ...
    @Id
    @Column(name="id")
    @GeneratedValue
    public Integer getListId() {
        return listId;
    }
    ...
    @OneToMany(mappedBy="todoList")
    public Set<Todo> getTodos() {
        return todos;
    }
   ...
    @ManyToMany(mappedBy="todoLists")
    public Set<User> getUsers() {
        return users;
    }
}
By default, some of the relationship types are retrieved lazily while some are loaded eagerly. The TodoList associated with an Todo is retrieved eagerl, because the fetch mode for the @ManyToOne annotation, that is defined for the Todo is defaulted to EAGER. This is because each eagerly fetched relationship turns into an additional JOIN tacked onto the basic SELECT statement to retrieve the entity. Below I have provided a table that outlines the default fetch behavior for the different types of relationship annotations.

Tutorial: Review of JPA EntityManager Operations for the Component Developer Exam-a6-defaultfetchbehavior.jpg
Table: Default Fetch Behaviour for Different Relationship Types

Updating Entities

The EntityManager will always ensure that changes to attached entities are always saved into the database. So itís not really necessary to be concerned with manually calling any methods to update the entity. This feature of JPA based persistence hides data synchronization behind the scenes and allows entities to behave like POJOs. So you can have a business method that makes changes to a POJO and at the end not be concerned with the synchronization of itís new state to the database. It will be done for you by the EntityManager.

Detached Entities and Merge Operations

As it it is difficult to maintain entities attached at all times since often they will be serialized at the web tier and changed, outside the scope of the EntityManager. Also since stateless session beans will almost never pull the same bean instance from the method ready pool to handle a client request, there is no guarantee an entity will be handled by the same EntityManager instance across method calls. This makes the idea of automating persistence impossible.

It is because of this, that the Java Persistence specification allows you to merge state changes to a detached entity back into the relational database using the merge method. An example is shown below:

Java Code: Example of merge operation
public Todo updateTodo(Todo todo) { 
   entityManager.merge(todo); 
   return todo;
}
The database is updated with the data from the Todo entity on the return of the merge method. This will only work if the entity already exists in the database. If it doesnít exist or has been deleted via the remove method, the merge will throw an IllegalArgumentException. This is the case even if the DELETE statement has not been issued yet.

Merging Relationships

Tutorial: Review of JPA EntityManager Operations for the Component Developer Exam-a6-reattachadetachedentity.jpg
Figure: Attaching a Detached Entity using merge() method

One of the challenges of the merge method is for entities associated with the entity. This behavior is controlled by using the cascade element of the @OneToOne, @OneToMany, @ManyToOne, and @ManyToMany annotations. When the CascadeType is set to either ALL or MERGE, the related entities are merged. An example of this with the Todo entity with the cascade element is set to MERGE is shown below:

Java Code: Definition of CascadeType with MERGE
public class Todo { 
@ManyToOne(cascade=CascadeType.MERGE)
    public TodoList getTodoList() {
In general, it is recommended that you call the merge method from within a transactional context to be safe. Otherwise it will throw a TransactionRequired-Exception. This will differ from one persistence provider to another but it is generally true for all of them.

Deletion Operations

The final cycle of methods for an entity is the deletion of an entity. The EntityManager provides a method called remove for this. It is shown in the listing below:

Java Code: Example of delete operation
public void deleteTodo(Todo todo) {
   entityManager.remove(entityManager.merge(todo));
}
One key thing to notice about this listing is that first we have to attach the entity to the EntityManager by use of the merge method. This is for the obvious reason that a remove will only work on attached entities. If the entity is detached the remove method will throw an llegalArgumentException. The database statement that is used for the delete will look like the following for the Todo record:

Java Code: Example of SQL DELETE Statement
DELETE FROM TODO WHERE todo_id = 123
Note that the DELETE statement may not necessarily be issued immediately but will be issued the next time a transaction context is available. This is similar to the persist and merge methods in this regard. Irrespective, the EntityManager will mark the entity as removed so no changes to the entity are synchronized.

Cascading Remove Operations
As with the other CRUD methods, you must set the cascade element of a relationship annotation to either ALL or REMOVE for related entities to be removed with the invocation of the remove method. An example of this is shown below for the TodoList:

Java Code: Example of CascadeType of REMOVE
@Entity 
public class TodoList {
@OneToOne(cascade=CascadeType.REMOVE) 
public Set setTodos() {
In the listing shown, itís obvious that the Todos will no longer exists once the TodoList is gone. So it is logical that they are removed when the TodoList is deleted. Generally the cascading removal tend to happen primarily with one-to-one and one-to- many relationships.

Flush Operations

When the EntityManager does a flushing operation what the EntityManager will do is to synchronize with the database for all the persist, merge and remove operations that have been performed but have not caused immediate database changes. The real purpose for allowing for this buildup of database operations before there actual application to the database is performance optimization. By batching SQL as much as possible instead of performing every database operation when a request is created by an EntityManager operation saves a great deal on communication overhead as well as avoiding possible delays with the database.

The default for database flush mode is AUTO which will cause the EntityManager to perform a flush operation automatically when required. This generally occurs for transaction-scoped EntityManagers at the end of a transaction and for application-managed or extended-scope EntityManagers when the persistence context is closed. Also if entities with pending changes are being used in a query, the persistence provider will flush changes to the database before executing the query.

If you want greater control over database synchronization, you can set the flush mode to COMMIT. The way to do this is shown in the code below:

Java Code: Example of setting flush mode
entityManager.setFlushMode(FlushModeType.COMMIT);
In this flush mode, the persistence provider will synchronize with the database only when a transaction is committed. What this ultimately means is that you are now responsible for synchronizing the entity state with the database before executing any queries. If you forget, your application can easily end up in an inconsistent state since the EntityManager query will return stale entities from the database. Irrespectively, you can always explicitly flush the EntityManager, which will synchronize the state of all managed entities within the database, when needed by doing the following:

Java Code: Example of flush operation
entityManager.flush();
Note that manual flushing shouldnít be abused. Use it in moderation and only when required. The key lesson to derive from flush operations is that batching database synchronization requests is a good optimization strategy and should be preserved.

Refresh Operations

Sometimes a user can be making changes to an entity and need to discard it or undo the changes and repopulate it with the original data from the database. This is the purpose of the refresh operation. It will repopulate entity data from the database. In other words, given an entity instance, the persistence provider matches the entity with a record in the database and resets the entity with retrieved data from the database as shown in figure

Tutorial: Review of JPA EntityManager Operations for the Component Developer Exam-a6-repopulatingentityusingrefresh.jpg
Figure: Repopulating Entity using Refresh after an Undo Operation

While the refresh method is not used frequently, there are some circumstances where it is extremely useful. The method is used to undo changes made by the TudoListBusiness client and return the repopulated entity with data from the database. The code for what is shown in the figure is provided below:

Java Code: Example of undo with refresh operation
public Item undoTodoListChanges(TudoList todoList) { 
   entityManager.refresh(entityManager.merge(todoList)); 
return todoList;
}
Note the inclusion of the merge operation. This is because similarly to the flush() operation, the refresh method only works on managed entities. Also the refresh method uses the entity identity to match database records so please ensure that the entity being refreshed exists in the database.

The two situations in which refresh are commonly used is in long running transactions and in cases where we want to update fields in an entity which itís values are provided by the database. In the listing shown below, we have a method called addTodoList, where after adding a new TodoList record to the database a TodoList entity is returned when the method has completed. Generally we would want the lastUpdate field of the TodoList to be set by the database system time when the TodoList is inserted into the database. As the EntityManagerís persist method only issues the INSERT statement, the TodoList that is returned will not have this field populated. This is remedied by using the refresh method.

Java Code: Example of persist operation with refresh
public Todo addTodoList(String tdname, boolean rssAllowed, int priority, 
   		String login, String firstName, String lastName, String email) { 
   User user = new User(); 
   user.setLogin(login); 
   user.setEmail(email);
   user.setFirstName(firstName);
   user.setLastName(lastName);
   TodoList todoList = new TodoList(); 
   todoList.setName(tdname); 
   todoList.setRssAllowed(rssAllowed); 
   HashSet set = new HashSet<User>(user);
   todoList.setUsers(set);
   entityManager.persist(todoList);
   entityManager.flush();
   entityManager.refresh(todoList);
   return todoList;
}
Note what has been done is to after the persist method is invoked, the EntityManager is flushed immediately so that the INSERT statement is executed and the generated value for lastUpdate is set by the database. Then refresh is called so that the entity is populated by the latest values. Another way of achieving this is to use the @GeneratedValue annotation for handling such fields.

Locking Operations and Entity Versioning

Application use a range of locking mechanisms in order to avoid concurrency issues. Having too many users trying to read or update the same data can easily grind application performance to a halt. An even worse scenario is to have a user working on data that is no longer valid because of changes due to another user. This is why locking mechanisms are so important. The locking strategies are generally broken into two camps:
  • Optimistic locking - is a strategy where problems associated with concurrency are assumed to occur rarely, and that if one is detected, that the problem can be resolved at that time.
  • Pessimistic locking - is a strategy where all of the involved database rows are locked for the time that a user shows an interest in modifying the entity.


When there are entities that are accessed concurrently in an application or when a merge is being done on detached entity instances, optimistic locking must be applied for those entities. In this case, a @Version attribute is added to the entities concerned. An example of this is given below:

Java Code: Example of use of @Version annotation
@Entity 
@Table(name = "TODO") 
public class Item implements Serializable {
   @Id 
   @Column(name = "TODO_ID") 
   protected Long todoId; 
   ... 
   @Version 
   @Column(name = "OPT_LOCK") 
   private Long version; 
   ...
}
The @Version can be used on a persistence field or property. It must be a numeric type such as int, long, Integer or Long and it needs to be mapped into a database column of the primary table to which the entity is mapped. Applications cannot set the version attribute. This is done directly by the persistence provider and will be automatically incremented when the persistence provider commits any changes to the database. In the case of a merge on a detached entity instance, the persistence provider checks the version column to ensure that the detached entity is not stale.

Entity Lifecycle

Similar to EJBs such as session beans or message driven beans, entities also have a lifecycle as well as callbacks. This is managed by the Java Persistence API in a manner similar to the EJB container providing synchronization and keeping track of the entities during itís lifecycle. There are callbacks for lifecycle events such as persist, load, update and remove. You have alot of flexibility in terms of what you can do with these callback methods such as invoking EJBs or even making calls to JMS. In most cases, the callback methods are used for auditing, logging, validating data or sending notifications of changes to the database back to a particular entity. The Java Persistence specification permits you to setup callback methods on entity classes so that the entity instance is notified when a particular event occurs. You can also register entity listeners to intercept the same events.
Below is the list of callbacks supported by JPA:
@javax.persistence.PrePersist - Before the EntityManager persists an entity instance
@javax.persistence.PostPersist - After an entity has been persisted
@javax.persistence.PostLoad - After an entity has been loaded by a query, find, or refresh operation
@javax.persistence.PreUpdate - Before a database update occurs to synchronize an entity instance
@javax.persistence.PostUpdate - After a database update occurs to synchronize an entity instance
@javax.persistence.PreRemove - Before EntityManager removes an entity
@javax.persistence.PostRemove - After an entity has been removed
enti
It is not necessary to define entity lifecycle methods in the entity itself. It is considered best practice to define a separate entity listener class to receive the lifecycle callbacks. This approach will allow you to avoid adding unnecessary complexity to your domain model and make it easier to segregate all callback methods of the entities for which they are concerned. This is logical since entity callbacks are typically concerned with crosscutting concerns rather than business logic directly pertinent to the entity.

Entity Callbacks
If you decide to use callbacks on entity classes, there are a number of rules that must be followed:
  • Any entity bean instance registering a callback on any of the lifecycle events can only annotate a public, protected, private or package-protected method on the bean class.
  • The method that is being annotated must return void.
  • The method that is being annotated must throw no checked exceptions.
  • The method that is being annotated must have no arguments.


An example of an entity callback for Todo is provided below:
Java Code: Example of callback for Todo Entity
import javax.persistence.Entity; 
import javax.persistence.PostPersist; 
import javax.persistence.PrePersist;

/** * Represents a Todo which is able to receive JPA * events. */
@Entity public class EntityListenerTodo {
private String todoName;
public String getTodoName() { return todoName; } 
public void setTodoName(final String todoName) { this. todoName = todoName; }

/* * Event Listeners; fired by JPA and track state in the EventTracker */
@PrePersist
@SuppressWarnings("unused")
private void prePersist(){ ... }
@PostPersist
@SuppressWarnings("unused")
private void postPersist(){ ... }
...
}
The entity manager will invoke the appropriate annotated method on the entity bean class when an event is triggered on a particular managed entity instance.

Entity Listeners

One of the best ways to take advantage of entity callback events is to use entity listeners. Entity listeners are classes used to generically intercept entity callback events. They can be attached to an entity class through XML or binding annotation. The methods are assigned on the listener class to intercept a specific event. These methods must do the following:
Have a void return
Take one Object parameter, the entity instance on which the event is triggered
An example of an auditor entity listener is shown below:

Java Code: Example of entity listener
public class TodoMonitor { 
...
public TodoMonitor() {}
@PrePersist 
@PreUpdate 
public void monitorTudo(Todo todo) {
         if (todo.getDescription() > 
            TodoMonitor.MONITORING_DESCRIPTION) {
         notificationManager.sendTodoEmailAlert(item);
      }
   }
}
@Entity 
@EntityListeners(com.acme.tudo.persistence.TodoMonitor.class) 
public class Item implements Serializable {
Note how you can apply the entity listener to an entity class by using the @javax.persistence.EntityListeners annotation:

Java Code: The boilerplate structure for EntityListener
package javax.persistence;

@Target(TYPE) 
@Retention(RUNTIME) 
public @interface EntityListeners
{
   Class[] value();
}
You can also intercept the callback event of an entity class by specifying a number of entity listeners:

Java Code: Example of entity listener for callback event
@Entity
@EntityListeners ({TodoMonitor.class})
public class EntityListenerTodo
{
   ...
}
By using @EntityListener annotation on the EntityListenerTodo entity class, any callback methods within those entity listener classes will be invoked whenever EntityListenerTodo entity instances interact with a persistence context.

Default Entity Listeners

Default entity listeners can be applied to every entity class in the persistence unit by using the <entity-listeners> element under the top-level <entity-mappings> element in the ORM mapping file. So if you want to apply the TodoMonitor listener to every entity class in a particular persistence unit, the mapping would be as is shown below:

XML Code: Application of entity listener to entity class
<entity-mappings> 
   <entity-listeners>
      <entity-listener class="com.acme.tudo.persistence.TodoMonitor"> 
         <post-persist name="postInsert"/> 
         <post-load name="postLoad"/>
      </entity-listener> 
   </entity-listeners>
</entity-mappings>
You can also use the @javax.persistence.ExcludeDefaultListeners annotation to turn off default entity listeners to an entity class. By applying either the @ExcludeDefaultListeners or the XML equivalent to the EntityListenerTodo, the TodoMonitor will be turned off:

Java Code: Example of @ExcludeDefaultListeners annotation
@Entity
@ExcludeDefaultListeners 
public class NoEntityListenersEmployee { 
   ... 
}
Inheritance with Listeners

When you put in place an inheritance hierarchy of entity listeners, any subclass will inherit these entity listeners. The subclass and superclass will be attached when the subclass has entity listeners applied to it.

Java Code: Example of entity listener inheritance
@Entity
@EntityListeners(TodoMonitor.class) 
public class SingleEntityListenerTodo
{
   ...
}

@Entity
@EntityListeners(AnotherListener.class) 
public class DoubleEntityListenerTodo extends SingleEntityListenerTodo{
   ...
}
Note that since we have more than one listener is listed, the execution order is determined by the order in which they are listed in the annotation or deployment descriptor as well as the OO construction inheritance rules. So based on the listing above, the order will be SingleEntityListenerTodo first and then DoubleEntityListenerTodo. It is not possible to control the order of execution programmatically. But you can exclude default and superclass listeners from being executed at all.

Tutorial: Review of JPA EntityManager Operations for the Component Developer Exam-a6-listenerexecutionorder.jpg
Figure: Order of Execution for Entity Listeners

Best Practices

Here are a list of best practices to follow for entity operations:
  • Use container-managed entity managers. If youíre enterprise application is going to be deployed in a Java EE container, use container-managed entity managers.
  • Use declarative transactions. This is something to be done in conjunction with container-managed EntityManager. You can then avoid all the details of managing entity transactions, or Entity Lifecycles.
  • Avoid entity managers in the web tier. Injecting entity managers into the web tier is to be avoided since the EntityManager interface is not thread-safe. It is recommended that you use a JNDI lookup for a container-managed EntityManager in conjunction with the Session Facade design pattern. Then you can take advantage of session beans.
  • Use the Entity Access Object pattern. This is the EJB3 equivalent of the Data Access Object pattern that is used with Hibernate or TopLink. Encapsulate all of the EntityManager API calls in an entity access object. This will allow you to abstract the EntityManager API from the business tier.
  • Separate callbacks into external listeners. As mentioned before as listeners on entity lifecycle callbacks tend to deal with crosscutting concerns such as auditing and logging code, it is best to separate this from your business domain model. Instead you encapsulate these crosscutting concerns in external entity listener classes. This also gives you the flexibility of being able to change listeners when required.


Thatís itís for Entity Operations for the Component Developer Exam. In the final article on the Java Persistence Specification, we will look at Persistence Units and Persistence Contexts.