Program guide > Programming with system APIs and plug-ins > Persistent store plug-ins

JPAEntityLoader plug-in

The JPAEntityLoader plug-in is a built-in Loader implementation that uses Java™ Persistence API (JPA) to communicate with the database when you are using the EntityManager API. When you are using the ObjectMap API, use the JPALoader loader.

Loader details

Use the JPALoader plug-in when you are storing data using the ObjectMap API. Use the JPAEntityLoader plug-in when you are storing data using the EntityManager API.

Loaders provide two main functions:

  1. get: In the get method, the JPAEntityLoader plug-in first calls the javax.persistence.EntityManager.find(Class entityClass, Object key) method to find the JPA entity. Then the plug-in projects this JPA entity into entity tuples. During the projection, both the tuple attributes and the association keys are stored in the value tuple. After processing each key, the get method returns a list of entity value tuples.

  2. batchUpdate: The batchUpdate method takes a LogSequence object that contains a list of LogElement objects. Each LogElement object contains a key tuple and a value tuple.

    To interact with the JPA provider, first find the eXtreme Scale entity based on the key tuple. Based on the LogElement type, you run the following JPA calls:

    • insert: javax.persistence.EntityManager.persist(Object o)

    • update: javax.persistence.EntityManager.merge(Object o)

    • remove: javax.persistence.EntityManager.remove(Object o)

A LogElement with type update makes the JPAEntityLoader call the javax.persistence.EntityManager.merge(Object o) method to merge the entity. However, an update type LogElement might be the result of either a o) call or an attribute change of the eXtreme Scale EntityManager managed-instance. See the following example: em = og.getSession().getEntityManager();
Consumer c1 = (Consumer) em.find(Consumer.class, c.getConsumerId());
c1.setName("New Name");

In this example, an update type LogElement is sent to the JPAEntityLoader of the map consumer. The javax.persistence.EntityManager.merge(Object o) method is called to the JPA entity manager instead of an attribute update to the JPA-managed entity. Because of this changed behavior, some limitations exist with using this programming model.

Application design rules

Entities have relationships with other entities. Designing an application with relationships involved and with JPAEntityLoader plugged in requires additional considerations. The application should follow the following four rules, described in the following sections.

Limited relationship depth support

The JPAEntityLoader is only supported when using entities without any relationships or entities with single-level relationships. Relationships with more than one level, such as Company > Department > Employee are not supported.

One loader per map

Use the Consumer-ShippingAddress entity relationships as an example, when you load a consumer with eager fetch enabled, you could load all the related ShippingAddress objects. When you persist or merge a Consumer object, you could persist or merge related ShippingAddress objects if cascade-persist or cascade-merge is enabled.

You cannot plug in a loader for the root entity map which stores the Consumer entity tuples. You must configure a loader for each entity map.

Same cascade type for JPA and eXtreme Scale

Reconsider the scenario where the entity Consumer has a one-to-many relationship with ShippingAddress. You can look at the scenario where cascade-persist is enabled for this relationship. When a Consumer object is persisted into eXtreme Scale, the associated N number of ShippingAddress objects are also persisted into eXtreme Scale.

A persist call of the Consumer object with a cascade-persist relationship to ShippingAddress translates to one javax.persistence.EntityManager.persist(consumer) method call and N javax.persistence.EntityManager.persist(shippingAddress) method calls by the JPAEntityLoader layer. However, these N extra persist calls to ShippingAddress objects are unnecessary because of the cascade-persist setting from the JPA provider point of view.

To solve this problem, eXtreme Scale provides a new method isCascaded on the LogElement interface. The isCascaded method indicates whether the LogElement is a result of an eXtreme Scale EntityManager cascade operation. In this example, the JPAEntityLoader of the ShippingAddress map receives N LogElement objects because of the cascade persist calls. The JPAEntityLoader finds out that the isCascaded method returns true and then ignores them without making any JPA calls. Therefore, from a JPA point of view, only one javax.persistence.EntityManager.persist(consumer) method call is received.

The same behavior is exhibited if you merge an entity or remove an entity with cascade enabled. The cascaded operations are ignored by the JPAEntityLoader plug-in.

The design of the cascade support is to replay the eXtreme Scale EntityManager operations to the JPA providers. These operations include persist, merge, and remove operations.

To enable cascade support, verify that the cascade setting for the JPA and the eXtreme Scale EntityManager are the same.

Use entity update with caution

As previously described, the design of the cascade support is to replay eXtreme Scale EntityManager operations to the JPA providers. If the application calls the ogEM.persist(consumer) method to the eXtreme Scale EntityManager, even the associated ShippingAddress objects are persisted because of the cascade-persist setting, and the JPAEntityLoader only calls the jpAEM.persist(consumer) method to the JPA providers.

However, if the application updates a managed entity, this update translates to a JPA merge call by the JPAEntityLoader plug-in. In this scenario, support for multiple levels of relationships and key associations is not guaranteed. In this case, the best practice is to use the javax.persistence.EntityManager.merge(o) method instead of updating a managed entity.

Parent topic:

Plug-ins for communicating with persistent stores

Related concepts

Write a loader

Use a loader with entity maps and tuples

Write a loader with a replica preload controller

Related reference

JPA loader programming considerations