A HibernateUtil class example to simplify JPA code

One of the most resource intensive components a developer encounters in JPA is the EntityManagerFactory. It's a resource used extensively in JPA applications because it generates the EntityManager objects that perform database operations. Every JPA operation depends on the EntityManagerFactory in some respect.

However, it does use significant resources so an application shouldn't create the EntityManagerFactory from scratch every time it's needed. Instead, a JPA-based application should strictly manage when EntityManagerFactory instances are instantiated and how they're accessed within the application. While there are many approaches to mitigate access to the EntityManagerFactory, the most common is to implement a HibernateUtil class.

In this Hibernate tutorial we will create a HiberanteUtil class to simplify JPA development by providing cache, creation, transaction management and error-handling functionality to data-driven Java applications.

PersistenceManager vs. the HibernateUtil class

Historically, the helper class that mitigates transactional access has been named HibernateUtil. But not every JPA implementation uses Hibernate, so Java applications often name this helper class PersistenceManager instead. Many data-driven applications use OpenLink or DataNucleus as their JPA implementation, so using the name Hibernate in such a domain model wouldn't make any sense. In this example we call our class HibernateUtil, but in most modern implementations, the name PersistenceManager makes more sense.

The first job of a modern HibernateUtil class is to cache the EntityManagerFactory in a manner that only allows the creation of one instance. The following code declares a static instance of the EntityManagerFactory. The getEntityManager() method ensures that it will only create one instance.

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

public class PersistenceManager {

  private static EntityManagerFactory factory;

  public static EntityManager getEntityManager () {
    if (factory == null) {
      EntityManagerFactory factory = 
        Persistence.createEntityManagerFactory("jpa-tutorial");
    }
    EntityManager entityManager = factory.createEntityManager();
    return entityManager;
  }
}

The simple singleton

The code above provides a rudimentary implementation of the singleton design pattern. A proper singleton implementation that works across multiple classloaders is more nuanced. Most enterprise frameworks like Spring and EJB3 allow developers to annotate a class with @Singleton and the framework handles the complexities of implementing this design pattern instead of the developer. If such a facility is available, use it. But for standalone applications or desktop applications that run on a standard JDK, the option to use dependency injection or Spring annotations won't be available.

Hibernate transaction management

Except for a few basic query calls, address database interactions within the scope of a transaction. As a result, client applications need to both begin a transaction and subsequently commit a transaction. This ability ensures that the change made within the scope of that transaction will persist. To facilitate this, our HibernateUtil class provides complementary beginTransaction() and commitTransaction() methods.

public static EntityManager beginTransaction() {
  EntityManager entityManager = getEntityManager();
  entityManager.getTransaction().begin();
  return entityManager;
}

public static void commitTransaction(EntityManager em){
  em.getTransaction().commit();
}

Notice how the beginTransaction() method actually returns the EntityManager object. The return helps because it allows a client to simultaneously begin a transaction and gain access to the EntityManager.

How to use the HibernateUtil class

Developers will notice the benefits of a HibernateUtil class when they compare the code written with it and without it. In the following code samples, look how the HibernateUtil class makes the syntax much more clear and complete.

public static void with(){
  EntityManager entityManager = 
      HibernateUtil.beginTransaction();
  Player p = new Player();
  p.setPassword("abc123");
  entityManager.persist(p);
  entityManager.getTransaction().commit();
}

Here is the same code implemented without the HibernateUtil class:

public static void withOut(){
  EntityManagerFactory emf = 
    Persistence.createEntityManagerFactory("jpa-tutorial");
  EntityManager entityManager = 
  emf.createEntityManager();
  entityManager.getTransaction().begin();
  Player p = new Player();
  p.setPassword("abc123");
  entityManager.persist(p);
  entityManager.getTransaction().commit();
}

Old school Hibernate sessions

The HibernateUtil class coded so far is exclusively JPA based. However, some ORM applications still need access to the legacy Hibernate Session object, not the JPA implementation's EntityManager.

Developers often include methods in a modern HibernateUtil class that provide access to the underlying Hibernate Session. A HibernateUtil class that mitigates access to the legacy Hibernate Session and SessionFactory object through JPA classes and methods is as follows:

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

public class LegacyHibernateUtil {

  private static EntityManagerFactory factory;

  public static Session getSession() {
    if (factory == null) {
      factory = 
         Persistence.createEntityManagerFactory("jpa-tutorial");
    }
    EntityManager entityManager = 
          factory.createEntityManager();
    Session session =   
      entityManager.unwrap(org.hibernate.Session.class);
    return session;
  }

  public static Session beginTransaction() {
    Session hibernateSession = getSession();
    hibernateSession.beginTransaction();
    return hibernateSession;
  }

  public static void commitTransaction(Session s) {
    s.getTransaction().commit();
  }

  public static void rollbackTransaction(Session s) {
    s.getTransaction().rollback();
  }

  public static void closeSession(Session s) {
    s.close();
  }

}

When developers use a HibernateUtil class, it can make code cleaner and easier to read, while also increasing its efficiency and requiring fewer resources.

View All Videos