Sunday, June 16, 2013

29 - Introduction-to-Criteria-API

Hibernate Criteria API is a more object oriented and elegant alternative to Hibernate Query Language (HQL). It’s always a good solution to an application which has many optional search criteria.

 HQL example
In HQL, you need to compare whether this is the first criteria to append the ‘where’ syntax, and format the date to a suitable format. It’s work, but the long codes are ugly, cumbersome and error-prone string concatenation may cause security concern like SQL injection.

public static List getUserDetailsRecord(Date startDate, Date endDate, Long volume, Session session) {

      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
      boolean isFirst = true;

      StringBuilder query = new StringBuilder("from UserDetails ");

      if (startDate != null) {
            if (isFirst) {
            query.append(" where date >= '" + sdf.format(startDate) + "'");
            } else {
            query.append(" and date >= '" + sdf.format(startDate) + "'");
            }
            isFirst = false;
      }

      if (endDate != null) {
            if (isFirst) {
            query.append(" where date <= '" + sdf.format(endDate) + "'");
            } else {
            query.append(" and date <= '" + sdf.format(endDate) + "'");
            }
            isFirst = false;
      }

      query.append(" order by date");
      Query result = session.createQuery(query.toString());

      return result.list();
}


Criteria example
In Criteria, you do not need to compare whether this is the first criteria to append the ‘where’ syntax, nor format the date. The line of code is reduce and everything is handled in a more elegant and object oriented way.

public static List getUserDetailsRecordCriteria(Date startDate,Date endDate,
        Long volume,Session session){

      Criteria criteria = session.createCriteria(UserDetails.class);
      if(startDate!=null){
            criteria.add(Expression.ge("date",startDate));
      }
      if(endDate!=null){
            criteria.add(Expression.le("date",endDate));
      }
      if(volume!=null){
            criteria.add(Expression.ge("volume",volume));
      }
      criteria.addOrder(Order.asc("date"));

      return criteria.list();
  }


HibernateTest.java
package org.yash.hibernate;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.Restrictions;
import org.yash.dto.UserDetails;

public class HibernateTest {

      public static void main(String args[]) {
           
            SessionFactory sessionFactory = new Configuration().configure()
                        .buildSessionFactory();
            Session session = sessionFactory.openSession();
            session.beginTransaction();

            Criteria criteria = session.createCriteria(UserDetails.class);
            criteria.add(Restrictions.eq("userName", "User 9"));
           
            List<UserDetails> users = (List<UserDetails>)criteria.list();          
            session.getTransaction().commit();
            session.close();
           
            for(UserDetails u:users){
                  System.out.println(u.getUserName());
            }
           

      }
}

UserDetails.java
package org.yash.dto;

import java.util.ArrayList;
import java.util.Collection;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;

@Entity
@NamedQuery(name="UserDetails.byId", query="from UserDetails where userId = ?") //HQL query - based on class name
@org.hibernate.annotations.Entity(selectBeforeUpdate=true)
public class UserDetails {
      /* @Id says "userId" is primary key */
      @Id @GeneratedValue (strategy=GenerationType.AUTO)
      private int userId;    
      private String userName;
      @OneToMany(cascade=CascadeType.PERSIST)
      private Collection<Vehicle> vehicle = new ArrayList<Vehicle>();
           
      public int getUserId() {
            return userId;
      }
      public void setUserId(int userId) {
            this.userId = userId;
      }
      public String getUserName() {
            return userName;
      }
      public void setUserName(String userName) {
            this.userName = userName;
      }
      public void setVehicle(Collection<Vehicle> vehicle) {
            this.vehicle = vehicle;
      }
      public Collection<Vehicle> getVehicle() {
            return vehicle;
      }
}

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="connection.driver_class">
            org.postgresql.Driver
        </property>
        <property name="connection.url">
            jdbc:postgresql://localhost:5433/hibernatedb
        </property>
        <property name="connection.username">postgres</property>
        <property name="connection.password">admin</property>

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

        <!-- SQL dialect -->
        <property name="dialect">
            org.hibernate.dialect.PostgreSQLDialect
        </property>

        <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>
       
        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>
       
        <!-- Drop and re-create the database schema on startup -->
            <property name="hbm2ddl.auto">update</property> 
<!-- create / update -->
   
          <!-- Names the annotated entity class -->
            <mapping class="org.yash.dto.UserDetails"/>    
            <mapping class="org.yash.dto.Vehicle"/>  
            <mapping class="org.yash.dto.TwoWheeler"/>     
            <mapping class="org.yash.dto.FourWheeler"/>    
           
    </session-factory>


</hibernate-configuration>

1 comment:

  1. Happy to found this blog. Good Post!. It was so good to read and useful to improve my knowledge as updated one, keep blogging. Hibernate Training in Electronic City
    Java Training in Electronic City

    ReplyDelete