Saturday 18 August 2012

Standalone Hibernate JPA In-Memory Example

This post describes an hibernate/JPA example in a standalone application (no application server or container required). It is available from Github, in the Standalone-Hibernate-JPA directory.

The purpose is to activate Hibernate with an in-memory database instance and illustrate basic CRUD (Create, Read, Update, Delete) operations. We use a simple JPA annotated item and Pojomatic for a nice string representation:
@Entity
@AutoProperty
public class Item implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long ID;

    // Setter & Getters, Pojomatic methods...

}
The CRUD operations are:
public static void save(Object o) {
    EntityTransaction et = EM.getTransaction();
    et.begin();
    EM.persist(o);
    et.commit();
}

public static <T> T get(Class<T> entityType, Object key) {
    return EM.find(entityType, key);
}

public static void update(Object o) {
    EntityTransaction et = EM.getTransaction();
    et.begin();
    EM.merge(o);
    et.commit();
}

public static void delete(Object o) {
    EntityTransaction et = EM.getTransaction();
    et.begin();
    EM.remove(o);
    et.commit();
}
The following:
private static EntityManagerFactory EMF;
private static EntityManager EM;

public static void main(String[] args) {

    // Creating resources
    EMF = Persistence.createEntityManagerFactory("Standalone");
    EM = EMF.createEntityManager();

    // Create
    Item i = new Item();
    i.setName("Item A");
    System.out.println("Before saving   : " + i);
    save(i);
    System.out.println("After saving    : " + i);

    // Read
    Item retr = get(Item.class, i.getID());
    System.out.println("Retrieved I     : " + retr);

    // Update
    i.setName("Item B");
    System.out.println("Updated         : " + i);
    update(i);
    retr = get(Item.class, i.getID());
    System.out.println("Retrieved II    : " + retr);

    // Delete
    System.out.println("Deleting        : " + i);
    delete(i);
    retr = get(Item.class, i.getID());
    System.out.println("Retrieved III   : " + retr);

    // Closing resources
    EM.close();
    EMF.close();

}
Generates the following output:
Before saving   : Item{ID: {0}, name: {Item A}}
After saving    : Item{ID: {1}, name: {Item A}}
Retrieved I     : {1}, name: {Item A}}
Updated         : Item{ID: {1}, name: {Item B}}
Retrieved II    : Item{ID: {1}, name: {Item B}}
Deleting        : Item{ID: {1}, name: {Item B}}
Retrieved III   : null
Notice that the id value is set after saving.

REM: The way transactions are used in the above example is not clean. Typically, one should wrap them in a try catch as following to trigger rollbacks when necessary:
EntityTransaction et = EM.getTransaction();
try {
    et.begin();
    EM.merge(o); // Or any other operations...
    et.commit();
} catch(Exception ex) {
    et.rollback();
    throw ex;
}

The Web Application version of this example is available here. More about JPA transaction types and the Java Transaction API (JTA) here.

--------------------

The persistence.xml file is configured as following (with hsqldb):
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0">

    <persistence-unit name="Standalone" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <class>com.jverstry.standalone.Item</class>
        <properties>
          <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver"/>
          <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:mem:testdb"/>
          <property name="javax.persistence.jdbc.user" value="sa"/>
          <property name="javax.persistence.jdbc.password" value=""/>
          <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
          <property name="hibernate.hbm2ddl.auto" value="create"/>
        </properties>

    </persistence-unit>

</persistence>
The dependencies are:
<dependency>
    <groupId>org.hsqldb</groupId>
    <artifactId>hsqldb</artifactId>
    <version>2.2.8</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>4.1.5.Final</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>4.1.5.Final</version>
</dependency>
<dependency>
    <groupId>org.pojomatic</groupId>
    <artifactId>pojomatic</artifactId>
    <version>1.0</version>
<type>jar</type>
</dependency>
    <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.6.6</version>
</dependency>
<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>6.0</version>
    <type>jar</type>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>1.0.0.GA</version>
    <scope>test</scope>
</dependency>

3 comments:

  1. Nice post ? By the way did I miss the try catch finally block in main method while closing resource ?

    Javin
    10 OOOPS and SOLID design principle for java developers

    ReplyDelete
    Replies
    1. This code is only created to illustrate general principles. Please refrain from posting links to your blog if it is not directly related to the matter (self-promotion vs reader value). Else, I will delete your comments. Thanks.

      Delete
  2. Good stuff. Look forward to the whole series.

    ReplyDelete