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
- 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.
- ORM consists of two concepts object-oriented and relational programming.
- Hibernate is an ORM framework where programmer describes the way objects are represented in database. Hibernate handles the conversion automatically.
- Hibernate provides implementation of JPA interfaces EntityManagerFactory and EntityManager.
- 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.
- 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
- https://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html
- https://docs.spring.io/spring-framework/reference/data-access/orm.html
- 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?
- When you want to check Repository’s save() method, you must use it.
- 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.