JPA - Persistence, EntityManagerFactory, EntityManager and PersistenceContext

What is EntityManager?

From Oracle documentation:

Interface used to interact with the persistence context.

An EntityManager instance is associated with a persistence context. A persistence context is a set of entity instances in which for any persistent entity identity there is a unique entity instance. Within the persistence context, the entity instances and their lifecycle are managed. The EntityManager API is used to create and remove persistent entity instances, to find entities by their primary key, and to query over entities.

EntityManager is part of the Java Persistence API. It implements the programming interfaces and lifecycle rules defined by the JPA 2.0 specification. We can access the Persistence Context by using the APIs in EntityManager.

JPA EntityManager is at the core of Java Persistence API. Hibernate is the most widely used JPA implementation.

JPA EntityManager

  1. One of the most important aspect of a program is connection with database. Database connection and transaction with database is considered as most expensive transaction. ORM is a very important tool in this regard. ORM helps in representing relations of database in terms of java objects.
  2. ORM consists of two concepts object-oriented and relational programming.
  3. Hibernate is an ORM framework where programmer describes the way objects are represented in database. Hibernate handles the conversion automatically.
  4. Hibernate provides implementation of JPA interfaces EntityManagerFactory and EntityManager.
  5. EntityManagerFactory provides instances of EntityManager for connecting to same database. All the instances are configured to use the same setting as defined by the default implementation. Several entity manager factories can be prepared for connecting to different data stores.
  6. JPA EntityManager is used to access a database in a particular application. It is used to manage persistent entity instances, to find entities by their primary key identity, and to query over all entities.

Set of managed entity instances within the same Entity Manager at any given time is called its Persistence Context.

And only one Java instance within the same Persistence Identity can exist in a Persistence Context at any given time.

If you put this on a relationship diagram it would look something like:

Persistence
     | 1
     | creates
     | *
EntityManagerFactory
     | 1
     | creates
     | *
EntityManager
     | *
     | manages
     | 1
PersistenceContext

Also the EntityManager and its related PersistenceContext are the so-called first-level cache. The second-level cache would be managed by the EntityManagerFactory.

Many applications create a layer of Data Access Objects–separate from the entities–that use EntityManager instances to query, load, and save entities. Often, these are singletons, and the entity manager instances inside the DAOs are local to the thread.

If you use a framework like Spring, the management of the EntityManager instances and transactions is completely automatic.

Spring documentation’s chapter on Object-Relational Mapping data access: https://docs.spring.io/spring-framework/reference/data-access/orm.html. The chapter gives some good tips on how to structure your application in a layered way that separates persistence concerns from the entities being persisted.

Reading material

  1. https://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html
  2. https://docs.spring.io/spring-framework/reference/data-access/orm.html
  3. https://www.digitalocean.com/community/tutorials/jpa-entitymanager-hibernate

TestEntityManager

The purpose of the EntityManager is to interact with the persistence context. Spring Data JPA abstracts you from the EntityManager through Repository interfaces. TestEntityManager allows us to use EntityManager in tests.

We can inject a TestEntityManager bean in Data JPA tests. If you want to use TestEntityManager outside of @DataJpaTest instances, just add @AutoConfigureTestEntityManager annotation.

The following example shows the @DataJpaTest annotation with TestEntityManager:

@DataJpaTest
class YourRepositoryTests {

  @Autowired
  private TestEntityManager entityManager;

  @Test
  void testExample() throws Exception {
    this.entityManager.persist(new Tutorial("Tut#1", "Desc#1", true));
    ...
  }
}

Why do we have repository and a TestEntityManager in the test?

We use both to save the same entity, what is the difference?

  1. When you want to check Repository’s save() method, you must use it.
  2. When you want to check other methods of Repository (not including save()), you must have data in database table, and you are NOT sure that Repository’s save() method is good or not, then you use TestEntityManager for persisting data.

Links to this note