Manipulating Entities with EntityManager

The EntityManager figures out how to persist the domain by looking at the ORM configuration, it performs the CRUD (create, read, update and delete) operations on the domain objects in this section you will learn about the EntityManager interface, the lifecycle of entities, the concept of persistence context and how to obtain an instance of EntityManager.

The EntityManager API manages the lifecycle of entities, it is the bridge between the OO and the relational worlds, as seen in the picture below

The EntityManager performs the following

Below is a table detailing the most common methods used of the EntityManager API

Method Signature
Description
public void persist(Object entity); Saves (persists) an entity into the database, also makes the entity managed
public <T> T merge(T entity); Merges an entity to the EntityManager's persistence context and returns the merged entity.
public void remove(Object entity); Removes an entity from the database
public<T> T find(Class<T> entityClass, Object primaryKey); Finds an entity instance by its primary key
public void flush(); Synchronizes the state of entities in the EntityManager's persistence context with the database
public mode setFlushMode(FlushModeType flushMode); Change the flush mode of the EntityManager's persistence context. The flush mode may either be AUTO or COMMIT. The default flush mode is AUTO, meaning that the EntityManager tries to automatically synch the entities with the database.
public FlushTypeMode getFlushMode(); Retrieves the current flush mode
public void refresh(Object entity); Refreshes (resets) the entity from the database
public Query createQuery(String name); Creates a dynamic query using a JPQL statement
public Query createNamedQuery(String name); Creates a query instance based on a named query on the entity instance.
public Query createNativeQuery(String sqlString);

public Query createNativeQuery(String sqlString, Class result);

public Query createNativeQuery(String sqlString, String resultSetMapping);
Creates a dynamic query using a native SQL statement
public void close(); Closes an application-managed EntityManager
public boolean isOpen(); Checks whether an EntityManager is open
public EntityTransaction getTransaction(); Retrieves a transaction object that can be used to manually start or end a transaction
public void joinTransaction(); Asks an EntityManager to join an existing JTA transaction

Entity Lifecycle

Entities are not loaded or managed by the container like session or MDB's, the EntityManager's task is to manage the entity and for the shortest time possible. Entities can be in a number of different states

An entities state is managed by the EntityManager, it makes sure it is in sync with the database. When the EntityManager starts to manage an entity, it synchronizes the entities state with the database, it also ensures that any changes are reflected in the database, it accomplishes this by holding an object reference to the managed entity and periodically checking for data freshness, if it finds that the entity has changed it synchronizes with the database. When the EntityManager can no longer reach the entity it is said to be detached ( it can be moved out of scope by either being removed, serialized or cloned), an entity will also be detached immediately when no transaction is associated with it.



An entity becomes attached when you use persist, merge, refresh or find, the state of the entity determines which method you will use (see above picture).

The merge and refresh methods are intended for entities that have been retrieved from the database and are in detached state, merge updates the database with the data held in the entity, and refresh does the opposite. You can detach an entity to upload it to the web tier, the web tier can then update it and then send it back, we then reattach it and it updates the database.

The persistence context plays a vital role in the internal functionality of the EntityManager, it is the persistence context that manages the lifecycle of an entity, in simple terms a persistence context is a self-contained collection of entities managed by an EntityManager during a given persistence scope. There are two different scopes

Transaction-scoped EntityManager If a persistence context is under transaction scope, entities attached during a transaction are automatically detached when the transaction ends. All persistence operations must occur inside the transaction, once the transaction is either committed or rolled back all entities are detached after they have been synchronized with the database.
Extended EntityManager

An Extended EntityManager can only be used with stateful session beans and lasts as long as the bean instance is alive. Until the EntityManager is closed by the session bean being destroyed the entities will remain managed, unless explicitly removed.

Now for an example, I have only highlighted the necessary parts to give to you an idea

Entity example @Stateless
public class ItemManagerBean implements ItemManager {

  // Inject the EntityManager instance
  @PersistenceContext(unitName="actionBazzar")
  private EntityManager entityManager;


  // No-arg constructor for creating ItemManagerBean instances by the container
  public ItemManagerBean() {}

  public Item addItem(String title, String description, byte[] picture, double initialPrice, long sellerId {

    Item item = new Item();
    item.setTitle(title)
    ...
    // Retrieves entity using primary key
    Seller seller = entityManager.find(Seller.class, sellerId);

    item.setSeller(seller);
    // Persist entity instance
    entityManager.persist(item);

    return item;
  }

  public Item updateItem(Item item) {
  
    // Merges changes to the database
    entityManager.merge(item);

  }

  public Item undoItemChanges(Item item) {

    // Refreshes entity from the database
    entityManager.refresh(entityManager.merge(item));

    return item;
  }

  public void deleteItem(Item item) {
  
    // Removes entity from the database
    entityManager.remove(entityManager.merge(item));

  }
}

Creating EntityManager Instances

To manage entities you must obtain an instance of an EntityManager, to do this you use the @PersistenceContext annotation. There are additional steps that must be completed in your container, I have these steps in another subject JBoss Enterprise Applications and an example in EJB 3 Integration.The container will take care of opening, closing and looking up the EntityManager behind the scenes. JPA fully supports creating application-managed EntityManagers that you can create, use and release, including controlling how the EntityManager handles transactions, this is useful if you want to use the JPA outside the container.

The @PersistenceContext definition is below

@PersistenceContext definition

@Target({TYPE, METHOD, FIELD})
@Retention(RUNTIME)
public @interface PersistenceContext {
  String name() default "";
  String unitName() default "";
  PersistenceContextType type default TRANSACTION;
  PersistenceProperty[] properties() default {};
}

Notes:

name - specifies the JNDI name of the persistence context
unitName - specifies the name of the persistence unit which is a group of entities used in a application
type - specifies the scope which can be either TRANSACTION (default) or EXTENDED

Here is an example of changing the scope, remember you cannot use the extended scope for stateless session beans or MDBs. It is primary used for managing state across method calls hence why is is only used with stateful beans.

EntityManager Scoping @PersistenceContext(type=PersistenceContextType.EXTENDED)
EntityManager entityManager;

One important point to remember is that the EntityManager is not thread safe, so do not go injecting them frivolously and do not inject them into a web component, yes there are ways around this (use SingleThreadModel) but don't go that route.

To access the EntityManager outside the container (you could be using Tomcat), you have to write code to control every aspect of the EntityManagers lifecycle.

@PersistenceUnit definition @Target({TYPE, METHOD, FIELD})
@Retention(RUNTIME)
public @interface PersistenceUnit {
  String name() default "";
  String unitName() default "";
}
EntityManager outside the container @Stateless
public class ItemManagerBean implements ItemManager {

  @PersistenceUnit
  private EntityManagerFactory entityManagerFactory;
  private EntityManager entityManager;

  public ItemManagerBean() {}

  @PostConstruct
  public void initialize() {
    entityManager = entityManagerFactory.createEntityManager();
  }
  ...
  public Item updateItem(Item item) {
    entityManager.joinTransaction();
    entityManager.merge(item);
    return item;
  }
  ...
  @PreDestroy
  public void cleanup() {
    if (entityManager.isOpen()) {
      entityManager.close();
    }
  }
  ...
}

The picture below shows the relationship between the various classes I mentioned above.



In Java SE environments the JTA is not available, so you must use resource-local transactions, the EntityTransaction interface can be used for this purpose.

Application-managed EntityManager // Get the EntityManagerFactory instance
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("actionBazaar");

// Create the EntityManager
EntityManager entityManager = entityManagerFactory.createEntityManager();

try {

  // Ceates a transaction
  EntityTransaction entityTransaction = entityManager.getTransaction();

  // Begin the transaction  
  entityTransaction.begin();

  // Merges the item (update the database)
  entityManager.persist(item);

  // Commits the transaction
  entityTransaction.commit();
}
finally
{
  // Close all the resources
  entityManager.close();
  entityManagerFactory.close();
}

If you are using Tomcat or Jetty some persistence providers recommended that you use the ThreadLocal pattern, it associates a single instance of the EntityManager with a particular request. You bind the EntityManager to a thread-local variable and set the EntityManager instance to the associated thread. Check your persistence provider's documentation if you require to use the ThreadLocal pattern.

ThreadLocal pattern

private static EntityManagerFactory emf;

public static final ThreadLocal<EntityManager> _threadLocal = new ThreadLocal<EntityManager>();

public static EntityManagerFactory getEntityManagerFactory() {
  if (emf == null) {
    emf = Persistence.createEntityManagerFactory("actionBazaar");
  }

  return emf;
}

public static EntityManager getEntityManager() {
  EntityManager entityManager = _threadLocal.get();

  if (entityManager == null) {
    entityManager = emf.createEntityManager();
    _threadLocal.set(entityManager);
  }
  return entityManager;
}

Managing Persistence Operations

A new entity is normally instantiated, and then all data that needs to go into the database is populated into the entity, this is normally passed in by the user. A persist method is then invoked to save the entity into the database. The persist method is intended to create new entity records in the database table not update existing ones, so make sure that the primary key used in not already there otherwise the persistence provider will throw a javax.persistence.PersistenceException. The persist method also causes the entity to become managed as soon as the method returns, the SQL statement generated is not immediately executed, in a transaction-scoped EntityManager this probably won't execute until the closing transaction is about to commit. So be careful not to rely on when the statement gets executed, but you can be sure that it will executed before the transaction completes. You can however manually flush the EntityManager at any time after the persist method, I will discuss this later.

By default the JPA does not persist related entities, in order to persist related entities we use the cascade attribute, you can set the cascade attribute to all, merge, persist, refresh or remove. The EntityManager will figure out all related entities, and will update, remove, etc accordingly.

persisting related entities public class User {

  @oneToOne(cascade=CascadeType.PERSIST)
  public void setBillingInfo(BillingInfo billing) {

Note: you can also use
CascadeType.MERGE
CascadeType.REFRESH
CascadeType.REMOVE (use for one-to-many and one-to-one)
CascadeType.ALL

JPA supports several ways to retrieve entity instances from the database, the best way is using the primary key with the find method. The first argument specifies the Java type of the entity to be retrieved, the second is the identity value (in this case the primary key value).

find method Seller seller = entityManager.find(Seller.class, sellerId);

The identity value 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.

Find by primary key using composite keys SellerPK sellerKey = new SellerPK();

sellerKey.setFirstName(firstName);
sellerKey.setLastName(lastName);

Seller seller = entityManager.find(Seller.class, sellerKey);

If the find method does not find any matches, the Entity-Manager will return null or an empty entity and your application should handle this. To improve performance the find method uses the Entity-Managers caching capability, if your persistence provider supports caching.

The find method will retrieve all of the entity fields when it is invoked (by default), sometimes this may not be desirable, Fetch Modes allow you to change this behavior to optimize the performance.

The Entity-Manager has two fetch modes, they are apply when entities are related to one another

Eager fetching

Also know as eager loading, this is the default option, the entity-manager will attempt to retrieve all of the entity field data when the find method is invoked, this could include BLOBs or CLOBs, which means that it could have an performance impact. Because BLOBs and CLOBs have a heavy impact on I/O operations these should only be loaded when necessary.

Other eager mechanisms are

  • @OneToOne (default)
  • @ManyToOne (default)
When eagerly fetching the EntityManager will use a JOIN in the SELECT statement to retrieve the entity.

Lazy fetching

Lazy fetching supports more than one mechanism

  • @Basic - specifiying a column with this annotation means that the data will only be load the first time it is accessed
  • @OneToMany (default)
  • @ManyToMany (default)

When lasy fetching the EntityManager would use separateSELECT statements and thus is less efficient than eager loading, when using entity relationships.

Manually specifying

@ManyToOne(fetch=FetchType.LAZY)
...

It is difficult to keep entities attached at all times, this is because entities will need to be detached and serialized at the web tier, where the entity is changed, which is outside the scope of the EntityManager, when using SLSB there is no guarantee that the same bean instance will be used, which means the entity will become detached, also entities become detached when transactions end. At some point you will want to reattach the entity to a persistence context to synchronize it with the database, the EntityManager's merge method is used for this. When using the merge method the entity may or may not be synchronized immediately, but it is guaranteed to be synchronized with the database sooner or later. If the entity has been removed then you will receive an IllegalArguementException error. By default entities that are associated with the entity being merged are not merged as well, you can control this using the cascade element of the @OneToOne, @OneToMany, @ManayToOne and @ManyToMany annotations. If the element is set to ALL or MERGE the related entities are merged.

merge method

entityManager.merge(item);

Note: this should be called from a transactional context

cascade element @ManyToOne(cascade=CascadeType.MERGE)

To remove an entity you use the remove method, remember this is not the same as detaching an entity. The remove method can only remove attached entities, again the remove may or may not happen immediately but is guaranteed to be issued at some point. Just with merging and persisting entities, you must set the cascade element of a relationship annotation to either ALL or REMOVE for related entities to be removed with the one passed to the remove method. Be careful as the cascade option is dangerous, there could be many relationships through the entities.

remove method

entityManager.remove(entityManager.merge(item));
entityManager.remove(item);

Note: the entity must be attached and should be called from a transactional context

cascade element @OneToOne(cascade=CascadeType.REMOVE)

Another one of the EntityManager methods is the the flush method, remember that persist, merge and remove operations may or may not happen immediately, the reason for this is to batch work and then execute it thus saving on the number of database calls which increases performance. By default the database flush mode is set to AUTO, this means that the EntityManager performs a flush operation when needed, this normally occurs at the end of a transaction or when the persistence context is closed for application managed or extended-scope EntityManagers.

You can set the EntityManager flush mode to COMMIT, thus the persistence provider will only synchronize with the database when the transaction commits, however it will be your responsibility to synchronize entity state with the database before executing a query, if you don't do this you could end up with an inconsistent application. You can also explicitly flush the EntityManager by using the flush method.

flush mode entityManager.setFlushMode(FlushModeType.COMMIT);
flush method entityManager.flush();

The last topic to discuss is the refresh method, this operation repopulates the entity data from the database overriding any changes in the entity.

refresh method entityManager.refresh(entityManager.merge(item);
entityManager.refresh(item);

Note: the refresh method only works on managed entities
Common usage

entityManager.persist(item);
entityManager.flush();
entityManager.refresh(item);

return item;

Note: here we persist the data, then flush it imemediately to synchronize the database, then obtain the most current data using the refresh method.

Entity lifecycle listeners

Entities have similar lifecycle callbacks to session and message-driven beans like PostContruct and PreDestroy, you can receive callbacks for lifecycle events like persist, load, update and remove, you could invoke an EJB, or use JMS. Most of the time you will use callbacks for logging, validating data, auditing, sending notifications or generating data after an entity has been loaded, these callbacks are the database triggers of the JPA world. All entity listeners are stateless in nature and you cannot assume that there is a one-to-one relationship between an entity instance and a listener instance.

Lifecycle Method
When it is performed
PrePersist Before the EntityManager persists an entity instance
PostPersist After an entity has been persisted
PostLoad After an entity has been loaded by a query, find, or refresh operation
PreUpdate Before a database update occurs to synchronize an entity instance
PostUpdate After a database update occurs to synchronize an entity instance
PreRemove Before EntityManager removes an entity
PostRemove After an entity has been removed

Now for an example of a entity listener

Listener public class ItemMonitor {
  ...
  public ItemMonitor() {}

  @PrePersist
  @PreUpdate
  public void monitorItem(Item item) {
    if (item.getInitialBidAmount() > ItemMonitor.MONTORING_THRESHOLD) {
      notificationManager.sendItemPriceEmailAlert(item);
    }
  }
}  
Entity @Entity
@EntityListeners(actionbazaar.persistence.ItemMonitor.class)
public class Item implements Serializable {
...

Sometimes you may want a default listener (for crosscutting) here you create your listener than you have to use the persistence file to implement it, there is no annotations to perform this

Listener public class ActionBazaarAuditor {
  ..
  @PrePersist
  @PostPersist
  ...
  @PostRemove
  public void logOperation(Object object) {
    Logger.log("Perform Persistence Operation on: " + object.getName() );
  }
}
persistence.xml <persistence-unit name="actionBazaar">
  ...
  <default-entity-listeners>actionbazaar.persistence.ActionBazzarAuditor.class</default-entity-listeners>
  ...
</persistence-unit>

Listeners follow OO inheritance rules, thus the picture below details the listener execution order. If there is more than one listener in a particular level, then the execution order is determined by the order in which they are listed in the annotation or deployment descriptor.

You can exclude default and super class listeners if you so wish

exclude listeners @Entity
@ExcludeDefaultListeners
@ExcludeSuperClassListeners

@EntityListeners(actionbazaar.persistence.ItemMonitor.class)
...

Best Practices

Here are some best practices, I am not going to go into too much details and therefore list them below, I will be updating this list as I become more experienced.