Switching from Hibernate mapping files to JPA

16

I’m just starting to build out an app that uses Hibernate. I started with Hibernate mapping files but switched over to using JPA annotations. I wanted to record the changes I needed to make and also a non-obvious exception (to my newbie eyes) and the solution.

When using Hibernate with mapping files you’ll have files like:

org/terracotta/reference/exam/domain/User.java
org/terracotta/reference/exam/domain/User.hbm.xml
org/terracotta/reference/exam/domain/HibernateUtil.java
hibernate.cfg.xml
log4j.properties

To switch to annotations, you’ll need to:

  1. Add hibernate-annotations and JPA jars
  2. Annotate your classes
  3. Modify hibernate.cfg.xml to use classes instead of mapping files
  4. Modify your HibernateUtil class to use a different configuration (this is the step that tripped me up)

To add the right jars, I’m using Maven and added the following additional dependencies:

<dependency>
  <groupId>javax.persistence</groupId>
  <artifactId>persistence-api</artifactId>
  <version>1.0</version>
</dependency>
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-annotations</artifactId>
  <version>3.3.1.GA</version>
</dependency>

There are many fine resources available on JPA annotations so I’m not going to discuss this in detail. You’ll have something that looks like this:

@Entity
@Table(name = “USERS”)
public class User {

@Id @GeneratedValue
@Column(name = “USER_ID”)
private Long id;

@Column(name = “FIRST_NAME”)
private String firstName;

@Column(name = “LAST_NAME”)
private String lastName;

@Column(name = “EMAIL”)
private String email;

// etc
}

To update your hibernate.cfg.xml file, you’ll want to change lines like this:

  <mapping resource="org/terracotta/reference/exam/domain/User.hbm.xml"/>

to something like this:

  <mapping class="org.terracotta.reference.exam.domain.User">

If you did all that and stopped there, you might see an exception like this:

Exception in thread "main" java.lang.ExceptionInInitializerError
	at org.terracotta.reference.exam.domain.HibernateUtil.<clinit>(HibernateUtil.java:15)
	at org.terracotta.reference.exam.domain.Main.main(Main.java:12)
Caused by: org.hibernate.MappingException: An AnnotationConfiguration instance is required to use <mapping class="org.terracotta.reference.exam.domain.User"/>
	at org.hibernate.cfg.Configuration.parseMappingElement(Configuration.java:1600)
	at org.hibernate.cfg.Configuration.parseSessionFactory(Configuration.java:1555)
	at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:1534)
	at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:1508)
	at org.hibernate.cfg.Configuration.configure(Configuration.java:1428)
	at org.hibernate.cfg.Configuration.configure(Configuration.java:1414)
	at org.terracotta.reference.exam.domain.HibernateUtil.<clinit>(HibernateUtil.java:13)

And, like me, you would be puzzled. It turns out that when using annotations you need to use AnnotationConfiguration, which is a subclass of Configuration, specific to annotations. So, your HibernateUtil might look like this instead:

package org.terracotta.reference.exam.domain;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;

public class HibernateUtil {
private static SessionFactory sessionFactory;

static {
try {
sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
} catch(Throwable t) {
throw new ExceptionInInitializerError(t);
}
}

public static SessionFactory getSessionFactory() {
return sessionFactory;
}

public static void shutdown() {
getSessionFactory().close();
}
}

Hope that helps someone down the line…

Comments

16 Responses to “Switching from Hibernate mapping files to JPA”
  1. Sam Halliday says:

    If you’re going the JPA route, why not just abandon all the Hibernate specific pieces and use the persistence.xml file and the EntityManager?

  2. Alex says:

    Will – haven’t gotten there yet.

  3. Joakim says:

    I’ve never understood WHY people want to put application configuration inside the source code. Using the XML files give you better separation between layers, and allows you to modify mappings without running the build script again. If you’re providing this software to clients, they can specialize the mappings to fit their database with your help over the phone or even on their own, instead of having to get your team to make a version just for them, or even worse, having to dig into your code. It’s plain wrong to hard code the application configuration.

  4. Alex says:

    Well, there are lots of applications where you don’t need that level of flexibility because you have more control over the app. Using annotations is:

    1) simpler
    2) better typed (fewer class names in external files)
    3) loses none of the flexibility since you can override the annotations in xml if needed

    That said, I don’t think either choice is right or wrong – different people will find or the other better in this scenario.

  5. I can’t believe that it’s been 2 years since I first used Hibernate Annotations. This blog was like a flashback for me, as I experienced a similar error. You would think a simple abstraction on top of the Configuration class (maybe just a factory for it?) would be enough to deal with this, as reading the hibernate.cfg.xml (i.e. the presence of a mapping element with a class attribute) file should be sufficient to imply which subtype of Configuration to use.

  6. Leendert Paul Diterwich says:

    Hope that helps someone down the line…

    Check :) thx..

  7. Bruno says:

    This was really helpful! I spent about 2 hours looking at my config files looking for something and took HibernateUtil for granted, what a huge mistake! Thanks a lot Alex :)

  8. Manvinder Singh says:

    Thanks Alex! That did puzzle me for long before I hit your solution.

  9. AK says:

    I was going nuts on this… thanks a lot!!!

  10. Luther Baker says:

    +1, similar use case.

  11. Adam W says:

    I had the same same issue. Thanks!

  12. Jonatas Chagas says:

    Nice dude!!

    If it wasn’t for you I would be still struggling with this!!

    =D

    Thanks man!

  13. Gabriele Iannetti says:

    Hello Alex!

    Thanks to your helpful post, I finally got over that error ( An AnnotationConfiguration instance is required to use <mapping class= ) using Configuration instead of the AnnotationConfiguration class.

    Spend some hours on it…

    Wish you a nice weekend!

    Cheers,
    Gabriele

  14. Anonymous says:

    Thank you !!!!!!!!!!!!!!!!

  15. Alan Mehio says:

    So sprong session factory configuratin will use

    …etc..

    instead of the one which is given in the spring 3 ref. documentation chapter 9

  16. Anonymous says:

    thank you!!!!

Speak Your Mind

Tell us what you're thinking...
and oh, if you want a pic to show with your comment, go get a gravatar!