HomeAbout MeContact
Java
Variety of EntityManagers
Piotr Szarpak
Piotr Szarpak
April 02, 2020
2 min
Make sure to subscribe to our newsletter and be the first to know the news.

Table Of Contents

01
Types of EntityManagers
02
Application-Managed Entity Managers
03
Container-Managed Entity Managers

Types of EntityManagers

EntityManagers are one of the most fundamental objects in JPA. It is quite easy to understand their basic role, however, it can be quite confusing when we look at the possible configurations in which we can use them.

EntityManagers can differ according to:

  • the way they are managed (Application, Container)
  • scope of their PersistenceContext (Transactional, Extended)
  • transaction management (Resource local, JTA)

To make things more complicated, not all combinations are allowed. For example, Container-Managed EntityManagers can work only with transaction management provided by JTA API.

entity managers

The above diagram represents possible EntityManager’s configuration options:

Application-Managed Entity Managers

The main feature of Application-Managed EntityManagers is that they are managed by the application ( by the programmer). It means, that the application code is responsible for their creation and closing.

To create an EntityManager object, we need to have javax.persistence.EntityManagerFactory object, which can be obtained in two ways:

  • If we work in a Java EE container, we can inject it:
@PersistenceUnit
private EntityManagerFactory entityManagerFactory;
  • create it manually :
EntityManagerFactory emf = Persistence.createEntityManagerFactory("unitname");

PERSISTENCE CONTEXT

As the diagram above shows, PersistenceContext for Application-Managed EntityManagers is by default EXTENDED, which means that it is not bound only to one transaction.

In this case, a new PersistenceContext is created when the method createEntityManager from EntityManagerFactory interface is invoked, and get detached when we invoke EntityManager’s close method or when the bean is serialized.

private EntityManagerFactory emf;
private EntityManager em;
public void run() {
methodA(); // create persistence context
methodB(); // perform some operations
methodC(); // detach persistence context
}
private void methodA() {
em = emf.createEntityManager(); // create persistence context
}
private void methodB() {
// do some more em operations
}
private void methodC() {
em.close();
}

In the above example, all three methods: methodA, methodB, and methodC work with the same PersistenceContext. It is important to remember, that every invocation of the createEntityManager method from the EntityManagerFactory interface will return an EntityManager object with a different PersistenceContext.

public void run(){
// method A and B work with a different persistence context
methodA();
methodB();
}
private void methodA() {
em = emf.createEntityManager(); // create persistence context
// perform some em operations
}
private void methodB() {
em = emf.createEntityManager(); // create another persistence context
// perform some em operations, this time in a different persistence context
}

TRANSACTION MANAGEMENT

Application-managed EntityManager for transaction management can use JDBC (RESOURCE_LOCAL) or JTA API. Which one will be used depends on the configuration in persistence.xml. The important thing is that JTA API can be used only when we work with a Java EE container.

In JDBC API, for transaction management responsible is javax.persistence.EntityTransaction interface. To obtain an instance that implements this interface, we have to use the getTransaction method from the EntityManager object.

Example of transaction management using JDBC API:

EntityManager em = emf.createEntityManager();
EntityTransaction tx = null;
try {
tx = em.getTransaction();
tx.begin();
// do some work
tx.commit();
}
catch (RuntimeException e) {
if ( tx != null && tx.isActive() )
tx.rollback();
throw e; // or display error message
}
finally {
em.close();
}

In JTA, we manage transactions using javax.transaction.UserTransaction interface. However, we don’t have to use it because, by default in JTA, the container is responsible for managing our transactions- it is called CMT (Container-Managed Transactions). In this case, the container will start the transaction as soon as the method begins and will commit it just before the method exits. All we need to do is manage our EntityManger (as we work in Application-Managed mode):

public void method() {
// start of the transaction
EntityManager em = null;
try {
em = emf.createEntityManager(); // new persistence context
// do some operations with EntityManager
} finally {
if (em != null) {
em.close(); // end persistance Context
}
// end of the transaction
}

While working with JTA API, if we want to manage our transaction manually, we have to annotate our bean with @TransactionManagement annotation with TransactionManagementType set to BEAN value. In this case, we have to:

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class EJBBean{ ... }

Now we can manage our transaction using javax.transaction.UserTransaction interface. We can obtain it at least in two ways: we can inject it with @Resource annotation, or we can inject javax.ejb.EJBContext interface which has method getUserTransaction that returns an instance of the UserTransaction interface.

Example of managing transactions in JTA:

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class EJBBean {
...
@Resource
UserTransaction ut;
public void methodA() throws Exception {
EntityManager em = null;
try {
ut.begin();
em = emf.createEntityManager(); //perform some update/insert with em
ut.commit();
} catch (Exception ex) {
ut.rollback();
throw ex;
} finally {
if (em != null) {
em.close();
}
}
...

Container-Managed Entity Managers

Container-managed EntityManagers are those kind of EntityManagers that are created and closed by the container. To make the EntityManager container-managed, all we need to do is inject it with @PersistenceContext annotation, with unitName defined in the persistence.xml file:

@PersistenceContext(unitName ="unitName")
private EntityManager entityManager;

PERSISTENCE CONTEXT

Because Container-Managed EntityManager is managed by the container, its PersistenceContext also is managed by the container-which by default is transaction-scoped. This means that the PersistenceContext lives as long as the transaction lives.

We can extend PersistenceContext to extended scope by adding type=PersistenceContextType.EXTENDED to @PersistenceContext annotation:

@PersistenceContext(unitName="unitName", type=PersistenceContextType.EXTENDED)
EntityManager em;

In this case, because PersistenceContext is associated with EntityManager, it lives as long as the bean lives. We can remove it programmatically by invoking the method with @Remove annotation, which will remove our bean from the container:

@Remove
public void remove() {
}

TRANSACTION MANAGEMENT

In Container-Managed EntityManager we can use only JTA API for transaction management. We can handle the transactions manually or let the container do it (the same as in Application-Managed EntityManager).

If we let the container manage our transaction and will have Container-Managed EntityManager, sample insert method will look like this:

@PersistenceContext(unitName="unitName")
EntityManager em;
public void insert(ClassStudent student) {
em.persist(student);
}

Tags

Share

Piotr Szarpak

Piotr Szarpak

Java passionate

Sed commodo, est quis maximus fermentum, massa ipsum euismod neque, in varius risus tellus quis lacus. Sed ac bibendum odio.

Expertise

Java > 11
DDD
Spring
Databases

Social Media

githubtwitterwebsite

Related Posts

Java Transaction API + EJB
Java Transaction API + EJB
April 10, 2020
2 min
© 2024, All Rights Reserved.
Powered By

Quick Links

Advertise with usAbout UsContact Us

Social Media