Friday, January 18, 2013

Eliminating hibernate boiler plate code


While using Hibernate, we use below mentioned code each time, we perform any database operation.
Session session = sessionFactory.openSession();
session.beginTransaction();
try {
 // your purposefull code goes here

 session.getTransaction().commit();
 return object;
} catch (Exception exception) {
 session.getTransaction().rollback();
 throw new RuntimeException(exception);
} finally {

 session.disconnect();
}
 We can eliminate the duplicity of this code by using the strategy, where this code will reside only  in HibernateUtil and while performing database operation, we will focus only on database operation, we want to perform.
The infrastructure code is as mentioned below - 
HibernateStrategy.java
package hibernate;

import org.hibernate.Session;

public interface HibernateStrategy {
 Object execute(Session session);
}
HibernateUtil.java
package hibernate;

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

public class HibernateUtil {

 private static SessionFactory sessionFactory;

 static {

  sessionFactory = new AnnotationConfiguration().configure()
    .buildSessionFactory();
 }

 public static Object performAction(final HibernateStrategy strategy) {
  Session session = sessionFactory.openSession();
  session.beginTransaction();
  try {
   Object object = strategy.execute(session);
   session.getTransaction().commit();
   return object;
  } catch (Exception exception) {
   session.getTransaction().rollback();
   throw new RuntimeException(exception);
  } finally {

   session.disconnect();
  }
 }
}

The sample code using HibernateUtil is as mentioned below - 
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
 <session-factory>
  <property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>
  <property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
  <property name="hibernate.connection.url">jdbc:hsqldb:mem:InMemoryDatabase</property>
  <property name="hibernate.connection.username">sa</property>
  <property name="hibernate.connection.password"></property>


  <!-- JDBC connection pool (use the built-in) -->
  <property name="connection.pool_size">2</property>

  <property name="hibernate.hbm2ddl.auto">create-drop</property>
  <property name="hibernate.show_sql">true</property>

  <mapping class="hibernate.Student"></mapping>
 </session-factory>
</hibernate-configuration> 
Student.java
package hibernate;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "Student")
public class Student {

 @Id
 @GeneratedValue
 private int studentId;
 private String name;
 private int age;

 public Student(final String name, final int age) {
  this.name = name;
  this.age = age;
 }

 public Student() {
 }

 @Override
 public String toString() {
  return "Student [studentId=" + studentId + ", name=" + name + ", age="
    + age + "]";
 }
}

Maven dependency
<dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <version>4.11</version>
 <scope>test</scope>
</dependency>
<dependency>
 <groupId>org.hibernate</groupId>
 <artifactId>hibernate</artifactId>
 <version>3.2.7.ga</version>
</dependency>
<!-- <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate</artifactId> 
 <version>3.2.1.ga</version> </dependency> -->
<dependency>
 <groupId>org.hibernate</groupId>
 <artifactId>hibernate-annotations</artifactId>
 <version>3.2.1.ga</version>
 <exclusions>
  <exclusion>
   <artifactId>javax.transaction</artifactId>
   <groupId>jta</groupId>
  </exclusion>
 </exclusions>
</dependency>
<dependency>
 <groupId>javax.transaction</groupId>
 <artifactId>jta</artifactId>
 <version>1.1</version>
</dependency>
<dependency>
 <groupId>org.hsqldb</groupId>
 <artifactId>hsqldb</artifactId>
 <version>2.2.9</version>
</dependency>
HibernateUtilTest.java  (code to test above infrastructure)
package hibernate;

import java.util.List;
import junit.framework.TestCase;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.junit.Test;

@SuppressWarnings("unchecked")
public class HibernateUtilTest extends TestCase {

 @Test
 public void testHibernateUtil2() {

  HibernateUtil.performAction(new HibernateStrategy() {
   @Override
   public Object execute(Session session) {
    Student student = new Student("Salil Verma-Test1", 20);
    session.saveOrUpdate(student);
    return new Object();
   }
  });

  List studentList = (List) HibernateUtil
    .performAction(new HibernateStrategy() {
     @Override
     public Object execute(Session session) {
      Criteria criteria = session.createCriteria(
        Student.class).add(
        Restrictions.eq("name", "Salil Verma-Test1"));

      return criteria.list();
     }
    });

  assertNotNull(studentList);
  assertEquals(1, studentList.size());
 }
}