Cette page n'est pas disponible en français. Veuillez-nous en excuser.

ABIS Infor - 2011-11

Hibernate and JPA2

Gie Indesteege (ABIS) - 30 September 2011

Abstract

Persisting Java objects to a relational database can be done in several ways: using the native JDBC API or working with a persistence framework, that avoids a lot of plumbing work and more over offers additional features like transactional support, security, caching, ... The chase for a good persistence framework is open.

Java and persistency

The life time of objects in an application is limited. Keeping objects for future use is a challenge. Persisting objects in a database causes a real headache because of the object/relational mismatch. So let's look for some possible options.

Once you have decided which object attributes are to be persisted into a database, you can write your own Java code to create, read, update or delete (CRUD) the information in/from the RDBMS of your choice. The JDBC API provides all you need to interact with the database through classes like Connection, Statement and ResultSet and their associated methods. A small example to retrieve person information for all persons with a name starting with 'P':

   String querySQL = "Select pno, plname, pfname from persons" 
                     + " where plname like '" + "P%'"
   Connection con = DriverManager.getConnection(dbUrl, user, password);
   Statement stmt = con.createStatement();
   ResultSet rs = stmt.executeQuery(querySQL);
   while (rs.next()) { System.out.println(rs.getString("pno") + ", " +
                      rs.getString("pfname") + ", " + rs.getString("plname")); }
   stmt.close();

It works fine, but you have to do it all yourself: know SQL, setup and control the connection to the database, handle the type conversion and the resultset, catch exceptions (not shown in the code), decide on the transactional level ... A little relief of effort is possible by using 'preconfigured' DataSources, which will be in charge for controlling the connection to the database.

But the alternative of using a persistence framework, reduces the programming effort more drastically and moreover offers transactional features, security options, performance improvements, ... for free. So what is the offer?

Persistence frameworks

JPA

Java Persistence API is part of the JSR 220 (EJB 3) specification (part of Java EE 6), created as a common denominator of the proposals made by the Java Community Process for handling persistence in enterprise Java applications.

Persistence in this context covers three areas:

  • the API itself, defined in the javax.persistence package

How can I access the data from an object oriented point of view? What options are available to synchronise my objects with the database?

  • the Java Persistence Query Language (JPQL)

I want to 'tune' the generated SQL or write my own complex query.

  • object/relational metadata

How can I associate the object model with the database structure?

JPA is built on the strength of Java SE annotations, completed with an extensive implementation library and a flexible configuration. So if you want to save a person entity to the database:

  1. Don't forget that you do need a persistence provider - in the example we use EclipseLink:

Configuration persistence.xml

   <persistence xmlns="http://java.sun.com/xml/ns/persistence"...>
   <persistence-unit name="abis" transaction-type="RESOURCE_LOCAL">
      <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
      <class>be.demo.jpa.Person</class>
      <properties>
         <property name="javax.persistence.jdbc.driver"
value="org.apache.derby.jdbc.EmbeddedDriver"/> <property name="javax.persistence.jdbc.url" value="jdbc:derby:c:\DerbyDB"/> ... </properties> </persistence-unit> </persistence>

  1. Next define the entity to be mapped to the database:

Entity class Person.java

   @Entity
   public class Person{
       public Person() {}
       @Id @GeneratedValue
       private int personNumber;
       private String firstName, lastName;
       // getters and setters of attributes
   }

  1. Finally use the mapped entity object and bring it under supervision of the (configured) entity manager, controlled by a transactional context:

Sample program

   EntityManagerFactory emf = Persistence.createEntityManagerFactory("abis");
   EntityManager em = factory.createEntityManager();
   EntityTransaction tx = em.getTransaction();
   tx.begin();
   Person employee = new Person();
   //set some properties here
   em.persist(employee);
   tx.commit();

And that's all you need to do for persisting a person object into the database. Amazing? The real power however can be discovered in the more advanced features of cascaded updating, caching, lazy loading, list processing, querying, ... to name a few.

Hibernate

as developed by JBoss (Gavin King), is an implementation of the JPA spec (and yes, Hibernate is perhaps the most important influencer of the JPA spec), with additional options.

E.g.

  • the JPA spec defines in fetching strategies when data must be fetched from the data store, Hibernate provides also how the data can be fetched
  • JPA specifies caching levels, Hibernate goes on with possibilities to define how this caching can be accomplished
  • JPA provides the concept of User Types, Hibernate implements multiple custom User Types.
  • Hibernate provides additional annotations.

So you can see Hibernate as a superset of JPA. Classes and method names are different, but the idea is the same: provide a transparent persistency to the application developer.

JPA

Hibernate

EntityManager

Session

persistence.xml

hibernate.cfg.xml

persist

save

annotations

+ (specific) Hibernate annotations

JPQL (JPA Query Language)

HQL (Hibernate Query Language)
QBC (Query By Criteria)
QBE (Query By Example)

Another differentiator is that Hibernate offers additional features like logging, security, historical data, choice of connection pooling mechanisms, ... which adds to the value.

Other persistence frameworks like OpenJPA (Apache), MyBatis (Google), EclipseLink (Eclipse) or DataNucleus (Apache) are all based on the same ideas. An extensive list can be found on http://java-source.net/open-source/persistence.

Hibernate and JPA2

The standard JPA specification is evolving, perhaps under the 'pressure' of Hibernate and other influencers. The actual JPA2 (JSR 317) adds a.o.

  • type safe criteria API
  • support for persistently ordered lists (OrderColumn)
  • clear method to EntityManager interface to allow entities to be evicted from the persistence context
  • support for pessimistic locking and new lock mode types
  • additional mappings

These additional features are, as a matter of fact, also available in Hibernate.

Conclusion

Extending the life of your objects by persisting them to the database is no longer a 'plumber' activity based on JDBC. When you set up/configure a persistence framework and annotate the domain classes correctly, the correct synchronisation between your objects and the data base becomes a fact, even in a multi-user environment. However, keep your eyes open for tuning the configuration to optimal performance, whether you use pure JPA or enhanced with Hibernate (or other) features.

A more detailed and practical insight can be obtained by attending the ABIS course on "Hibernate and JPA" ( http://www.abis.be/html/en1309.html)