How JPA EntityManager handles Hibernate transaction management

The key to successful Hibernate transaction management is the JPA EntityManager. It's the only JPA component that can start transactions, commit transactions and hook into Hibernate transactions that are already in progress.

The JPA EntityManager is the cornerstone of Java persistence, and it is vital to helping you to understand how an object-relational mapping framework like Hibernate works.

EntityManager vs. Hibernate Session

For those with a history of Hibernate development, you'll find it interesting that under the covers, when a Hibernate-based distribution is used as the JPA provider, the EntityManager is really a wrapper around the Hibernate Session.

In fact, it's even possible to extract the Session out of the EntityManager and completely bypass JPA. This can actually be useful if a required method is available only in the Hibernate Session, and working through the SessionFactory to obtain a Session instance would be problematic.

JPA EntityManager example

In this EntityManager persist example, we will create a simple JavaBean named "Player" and decorate it with @Entity, @Id and @GeneratedValue annotations.

package com.mcnz.jpa.examples;
import javax.persistence.*;

@Entity 
public class Player {

   @Id @GeneratedValue
   private Long id;
   private String name;
   public Long getId() {
      return id;
   }
   public void setId(Long id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
}

An EntityManager persist example

After the developer creates the Player class, the next step is to gain access to the JPA EntityManager. A developer can obtain the JPA EntityManager through a multistep process that starts with the creation of the EntityManagerFactory. Factory creation is done when a developer invokes a method on the JPA's static Persistence context object and provides the name of the persistence unit, as specified in the persistence.xml file. In this example, the specified persistence unit is jpa-tutorial:

<persistence-unit name="jpa-tutorial">

Given this persistence unit, the method call to create the factory is as follows:

EntityManagerFactory emf =
     Persistence.createEntityManagerFactory("jpa-tutorial");

When a developer invokes the createEntityManager method on the factory, it provides access to the EntityManager, which can then be used to begin and end transactions.

EntityManager entityManager = emf.createEntityManager();
entityManager.getTransaction().begin();
// Transactional hibernate and JPA code goes here
entityManager.getTransaction().commit();
JPA EntityManagerFactory
The JPA EntityManagerFactory is coupled tightly with the persistence-unit name.

JPA and Hibernate transaction management

Once a JPA transaction has started, any entity bean that interacts with the EnityManager -- be it through a persist, merge or delete method call -- will have its state managed by Hibernate until the transaction commits. When the commit occurs, the state of all JavaBeans that have interacted with the JPA EntityManager are written to the underlying database.

entityManager.getTransaction().begin();
Player p = new Player();  
p.setPassword("abc123");
p.setName("Cameron");
entityManager.persist(p);
entityManager.getTransaction().commit();

This tutorial builds on previous JPA examples which use nothing but a JDK installation, a text editor to write code and the required Hibernate libraries in a local folder named hiblib. The following two JDK utility commands will compile and run the code:

C:\_workspace>javac -classpath "C:\_hiblib\*" C:\_workspace\com\mcnz\jpa\examples\Player.java
C:\_workspace> java -classpath "C:\_hiblib\*";C:\_workspace\ com.mcnz.jpa.examples.Player

It's my personal preference and recommendation to develop in an IDE such as Eclipse or NetBeans.

How to roll back a Hibernate transaction in JPA

A runtime exception won't necessarily short circuit Hibernate transaction management. Development teams can deal with such situations where data shouldn't persist to the database when an error occurs. Developers should put all business logic within a try catch block and call the rollback method of the current transaction to ensure that the relational database is left in the state it was in prior to the start of the transaction.

Here is the complete JPA persist example with the option to roll back a transaction included within the catch block:

public static void main(String args[]){
   // EntityManager persist example
   EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpa-tutorial");
   EntityManager entityManager = emf.createEntityManager();
   try {
      // Hibernate transaction management begins
      entityManager.getTransaction().begin();

      Player p = new Player();
      p.setPassword("abc123");
      p.setName("Cameron");
      p.setTest("Testing!!!");

      entityManager.persist(p);

      entityManager.getTransaction().commit();
      // Hibernate transaction management ends
      } catch(Exception e) {
         entityManager.getTransaction().rollback();
   }
}

As you can see, the JPA EntityManager plays a key role in Hibernate transaction management at runtime.

You can find the complete source code for this EntityManager persist example on GitHub.

View All Videos