databaseHibernateJPA

Hibernate Cheat Sheet

Recently I wanted to write a small state-of-the-art Hibernate application. To my surprise, I didn’t find information about Hibernate 4 and the XML-free documentation easily. It’s all there, but it’s buried under tons of old-school tutorials and Spring tutorials. So here’s my small collection of what I’ve found out.

I’ll describe both the standard JPA and pure Hibernate approach. That’s because I didn’t find out how to configure JPA without XML yet.

Dependencies

Well, I promised you “no XML”, but of course, this didn’t include the Maven pom.xml:

<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-core</artifactId>
   <version>4.3.8.Final</version>
</dependency>

<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-entitymanager</artifactId>
   <version>4.3.8.Final</version>
</dependency>
<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-core</artifactId>
   <version>4.3.8.Final</version>
</dependency>
compile 'org.hibernate:hibernate-core:4.3.8.Final'
compile 'org.hibernate:hibernate-entitymanager:4.3.8.Final'
compile 'org.hibernate:hibernate-core:4.3.8.Final'

Pure Java configuration of Hibernate

Configuring an XML file is all good and well – until I uploaded my app to a server with a different folder layout. My application wouldn’t start because it didn’t find the configuration file. Probably I could have moved it to the classes folder. Instead, I resorted to a pure Java solution. I like this version better because I can debug it. And because I know what I deliver. There’s nothing worse than an administrator modifying the database configuration in production without telling the development team.

Basically, you need a Configuration object. The properties – such as the SQL dialect, the name of the datasource and whether to create the database from scratch each time the server is started – are set by calling Configuration#setProperty(). Don’t forget to add the hibernate. prefix to the property name.

Don’t add the entity classes via Configuration#addClass(). This method requires an *.hbm file for each and every entity. Instead, use Configuration#addAnnotatedClass():

private static SessionFactory sessionFactory;

static {
    Configuration config = new Configuration()
       .setProperty("hibernate.dialect", 
                    "org.hibernate.dialect.HSQLDialect")
       .setProperty("hibernate.connection.driver_class", 
                    "org.hsqldb.jdbcDriver")
       .setProperty("hibernate.connection.url", 
                    "jdbc:hsqldb:mem:myFavoriteDB")
       .setProperty("hibernate.connection.username", "somebody")
       .setProperty("hibernate.connection.password", "IWillNotTellYou")
       .setProperty("hibernate.hbm2ddl.auto", "update")
       .setProperty("hibernate.show_sql", "true")

       .addAnnotatedClass(MyBusinessClass.class);

    StandardServiceRegistryBuilder ssrb = new StandardServiceRegistryBuilder()
       .applySettings(config.getProperties());
    sessionFactory = config.buildSessionFactory(ssrb.build());

}

The drawback of this approach is that you have to add each Entity individually. However, you can automate this with a few lines of reflection.

The SessionFactory has immutable state, so I suppose you can safely use it in a static final variable without opening a memory leak. However, it can be closed, so probably it’s a better idea to put it in an ApplicationScoped bean and release the SessionFactory in a method annotated by @PreDestroy.

Reading and writing entities (native Hibernate style)

The session object doesn’t implement the AutoClosable interface, so take care to close the connection correctly (even and especially if an exception is thrown):

Session session = sessionFactory.openSession();
try {
    List<HighScore> result = (List<MyBusinessClass) session
                    .createQuery("from MyBusinessClass order by birthdate desc")
                    .list();
    return result;
} finally {
    session.close();
}

I know about the criteria API, but I prefer the older SQL-like style. I’ve grown up with SQL, so it matches my mind model better.

Persisting data requires a transaction manager. Again, make sure you close it correctly in a try...finally block. For the sake of brevity, I omit them here:

Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
session.persist(score);
transaction.commit();
session.close();

Persistence.xml (JPA)

Now let’s have a look at the standard approach. Again, I was surprised I didn’t find out how to configure a JPA PersistenceUnit without at least a few lines of XML. There are a couple of vague hints in the internet, and it’s obviously possible: Spring does it (at least internally). If you know how to get rid of the persistence.xml file, please drop me a note. In the meantime, we can do with a very minimalist persistence.xml.

Put the persistence.xml into the META-INF of the classpath. If you use the standard directory layout of Maven, that’s src/main/resources. This is the shortest running version I successfully tested::

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
  <persistence-unit name="myFavoriteDBUnit" />
</persistence>

Configuring JPA with as little XML as possible

According to the Javadoc, both the EntityManager and the EntityManagerFactory must be released after use. So it might be a good idea to put them in a SessionScoped bean and release the resources in an @PreDestroy method. The following example takes a different approach. I wrapped the DAO functions in an AutoCloseable class which can be used in a try-with-resources block. Of course, this approach tends to create and release the EntityManagerFactory very often, so it may become a performance problem in production1.

public class MyJPADAO implements AutoCloseable {
  private EntityManagerFactory emf=null;
  EntityManager em=null;
  {
    Map<String, String> props = new HashMap<>();
    props.put("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
    props.put("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver");
    props.put("hibernate.connection.url", "jdbc:hsqldb:mem:myFavoriteDB");
    props.put("hibernate.connection.username", "somebody");
    props.put("hibernate.connection.password", "IWillNotTellYou");
    props.put("hibernate.hbm2ddl.auto", "update");
    props.put("hibernate.show_sql", "true");
    emf = Persistence.createEntityManagerFactory("myFavoriteDBUnit", props);
    em = emf.createEntityManager();
  }
  
  @Override
  public void close() throws Exception {
    if (null != em) em.close();  // try-catch omitted for brevity
    if (null != em) emf.close(); // try-catch omitted for brevity
  }
}

Note that I didn’t register the entities with the factory. JPA seems to scan the classpath and finds the entities automatically.

The DAO class can be wrapped in try-with-resource-statements like so:

    try (MyJPADAO dao = new MyJPADAO ()) {
      dao.save();
    }
    try (MyJPADAO dao = new MyJPADAO ()) {
      List result = dao.load();
    }

Loading data, JPA style

The query API doesn’t look much different from its Hibernate counterpart:

  private List load() {
    List resultList = em
              .createQuery("from MyBusinessClass order by birthday desc")
              .getResultList();
    return resultList;  
  }

Saving data, JPA style

JPA uses a different class for the transaction. Apart from the, the code looks similar to the Hibernate version we’ve seen above:

private void save() {
    EntityTransaction userTransaction = em.getTransaction();
    userTransaction.begin();
    MyBusinessClass demo = new MyBusinessClass();
    entity.setName("Tester");
    entity.setDate(new Date());
    em.persist(entity);
    userTransaction.commit();
}

Please note this example is a little sloppy with its error handling. Don’t forget the try-catch statements in real-world code!

Dig deeper

Hibernate documentation
JPA documentation

  1. I didn’t measure the impact on performance yet