Using Hibernate 3.5 as a JPA 2.0 Persistence Implementation
Are you interested in JPA 2.0, and you want to use Hibernate as your implementation? This tutorial shows you how easy it is to take your JPA annotated components and use the Hibernate 3.5 as your implementation.
In previous tutorials, we demonstrated how to configure a Hibernate 3.5 development environment, both using Hibernate mapping files and by using JPA annotated POJOs. However, since Hibernate 3.5 is fully JPA 2.0 compliant, it is not necessary to use the actual Hibernate APIs to do persistence. Instead, you can simply use the JPA 2.0 APIs, and avoid any references to the implementing Hibernate framework in your code.
So, how to you do it?
First off, you need a persistence.xml file that resides within a META-INF folder that resides off the application root. The persistence.xml file is in many ways similar to the hiberante.cfg.xml file, in so much as it holds information that the JPA implementation will use to connect to the database. Here's the persistence.xml file this example will use:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<persistence-unit name="PU">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.mcnz.model.GameSummary</class>
<exclude-unlisted-classes />
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.connection.url" value="jdbc:mysql://localhost/rps"/>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.connection.username" value="root"/>
<property name="hibernate.connection.password" value="password"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
Notice the name of the persistence-unit. It is named PU. When we ask the JPA persistence framework to provide our application with a component that will manage our entities, this is the name that is provide.
Once this persistence.xml file is configured, we can write some code that persists our JPA annotated POJOs to the database. This tutorial uses the exact same GameSummary class that was created in previous tutorials. For those who haven't been following along, here's what it looks like:
package com.mcnz.model;
import javax.persistence.*;
import org.hibernate.cfg.*;
import org.hibernate.tool.hbm2ddl.*;
@Entity
public class GameSummary {
@Id
@GeneratedValue
private Long id;
private String result, clientGesture, serverGesture;
private java.util.Date date;
public String getClientGesture() { return clientGesture;}
public void setClientGesture(String clientGesture) {
this.clientGesture = clientGesture;
}
public String getServerGesture() {return serverGesture;}
public void setServerGesture(String serverGesture) {
this.serverGesture = serverGesture;
}
public java.util.Date getDate() {return date;}
public void setDate(java.util.Date date) {this.date = date;}
public Long getId() { return id;}
public void setId(Long id) {this.id = id;}
public String getResult() {return result;}
public void setResult(String result) {
this.result = result;
}
public String toString() {
return "id: " + id + " result: " + result ;
}
}
So, with the persistence.xml file created and saved in the META-INF folder, and the POJOs that make up our domain model decorated with JPA 2.0 annotations, we can write some code that actually persists instances of our GameSummary class to the database. Here's a little runnable class, named the JpaRunner, that does just that:
package com.mcnz.model;
import javax.persistence.*;
public class JpaRunner {
public static void main(String args[]){
GameSummary gameSummary = new GameSummary();
gameSummary.setClientGesture("paper");
gameSummary.setServerGesture("scissors");
gameSummary.setResult("loss");
gameSummary.setDate(new java.util.Date());
EntityManagerFactory emf = Persistence.createEntityManagerFactory("PU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(gameSummary);
em.getTransaction().commit();
}
}
Essentially, the code simple creates an instance of the GameSummary class, and then obtains an EntityManager instance from the EntityManagerFactory. Notice how the EntityManagerFactory is created by the static call to the Persistence object's createEntityManagerFactory method, which takes the name of the persistence unit, PU, as was specified in the persistence.xml file.
Also notice that this program runs as a simple stand-alone application. JPA components are often part of modern Java EE 6 applications, but they don't need to be. In this case, Hibernate's JPA implementation is run successfully without the facilities of any EJB container whatsoever.
When this code runs, we see the following SQL spit out by Hibernate to the application logs:
Hibernate: insert into GameSummary (clientGesture, date, result, serverGesture) values (?, ?, ?, ?)
We also see the following record has been added to the gamesummary table in the database:
Knowing that the primary key of the persisted data is one (1), we can use the JPA EntityManager to read this data from the database. Here's how it looks:
package com.mcnz.model;
import javax.persistence.*;
public class JpaRunner {
public static void main(String args[]){
EntityManagerFactory emf = Persistence.createEntityManagerFactory("PU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
GameSummary gs = em.find(GameSummary.class, new Long(1));
System.out.println(gs.toString());
em.getTransaction().commit();
}
}
The find method of the EntityManager instance, when provided with the class type and the primary key, will query the database, and return a fully initialized GameSummary instance based on the associated record in the database. In this code, the Hibernate query, and the call to the toString() method of the GameSummary instance, prints out the following information to the console:
Hibernate: select gamesummar0_.id as id0_0_, gamesummar0_.clientGesture as clientGe2_0_0_, gamesummar0_.date as date0_0_, gamesummar0_.result as result0_0_, gamesummar0_.serverGesture as serverGe5_0_0_ from GameSummary gamesummar0_ where gamesummar0_.id=?
id: 1 result: loss
To update the record of interest so that the clientGesture is set to rock, and the result is set to win, we simply find the entity, as we did in the previous code snippet, update some properties, and then commit the transaction. No special update methods need to be called. So, the following code, when run, will update the underlying data in the database:
package com.mcnz.model;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class JpaRunner {
public static void main(String args[]){
EntityManagerFactory emf = Persistence.createEntityManagerFactory("PU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
GameSummary gs = em.find(GameSummary.class, new Long(1));
System.out.println(gs.toString());
em.getTransaction().commit();
}
}
When the JpaRunner is executed, we see the following code on the console:
Hibernate: select gamesummar0_.id as id0_0_, gamesummar0_.clientGesture as clientGe2_0_0_, gamesummar0_.date as date0_0_, gamesummar0_.result as result0_0_, gamesummar0_.serverGesture as serverGe5_0_0_ from GameSummary gamesummar0_ where gamesummar0_.id=?
Hibernate: update GameSummary set clientGesture=?, date=?, result=?, serverGesture=? where id=?
When we look in the database, we can see that the record with the id of one (1) has been updated with a result of win, and a clientGesture of rock, as is expected.
Deleting an Entity
To delete an entity, all we need to do is pass the entity in question ot the remove method of the EntityManager. The following code loads the entity with a primary key of 1 into the application, and then has that entity unceremoniously deleted.
package com.mcnz.model;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class JpaRunner {
public static void main(String args[]){
EntityManagerFactory emf = Persistence.createEntityManagerFactory("PU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
GameSummary gs = em.find(GameSummary.class, new Long(1));
em.remove(gs);
em.getTransaction().commit();
}
}
When this code runs, the record is removed from the database, and the following SQL can be found in the console logs:
Hibernate: select gamesummar0_.id as id0_0_, gamesummar0_.clientGesture as clientGe2_0_0_, gamesummar0_.date as date0_0_, gamesummar0_.result as result0_0_, gamesummar0_.serverGesture as serverGe5_0_0_ from GameSummary gamesummar0_ where gamesummar0_.id=?
Hibernate: delete from GameSummary where id=?