Java @ Desk: Hibernate | Java at your desk

Hibernate CascadeType Tutorial Example

In Hibernate 4, parent child relationship is defined either using OneToMany or ManyToOne or ManyToMany. But how to update, save or delete a child when the parent performs either update, delete or save operation.

org.hibernate.annotations.Cascade; and org.hibernate.annotations.CascadeType; enables the child persistance as soon as parents performs some operation.

There are various CascadeType in Hibernate like None, Save_Update, Delete, etc. We will understand one by one using Annotation example.

Consider below 2 classes. Person class can have multiple Address. There is One To Many Relationship
package com.pojo;

import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

@Entity
@Table(name = "Person")
public class Person implements java.io.Serializable {

 private Set<Address> addresses;

 @OneToMany(mappedBy = "person")
 public Set<Address> getAddresses() {
  return addresses;
 }

 public void setAddresses(Set<Address> addresses) {
  this.addresses = addresses;
 }
}


package com.pojo;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

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

 private Person person;

 @ManyToOne
 @JoinColumn(name = "person_id")
 public Person getPerson() {
  return person;
 }

 public void setPerson(Person person) {
  this.person = person;
 }
}


1) CascadeType None
If CascadeType is not given as shown above then we need to explicitly save a parent as well as all the childrens in to the session as shown below
Person person = new Person();
Address address1 = new Address();
session.save(person);
session.save(address1);




2) CascadeType.ALL : With this cascade type when a Parent is saved, updated, deleted Child will also gets saved, updated, deleted. No need to explicitly save or update or delete the childrens into the session.
private Set<Address> addresses;

@OneToMany(mappedBy = "person")
@Cascade( { CascadeType.ALL})
public Set<Address> getAddresses() {
 return addresses;
}

public void setAddresses(Set<Address> addresses) {
 this.addresses = addresses;
}
Person person = new Person();
Address address1 = new Address();
Address address2 = new Address();

person.setAddresses(new HashSet<Address>());
person.getAddresses().add(address1);
person.getAddresses().add(address2);

session.save(person);


3. CascadeType.SAVE_UPDATE: With this cascade type when a Parent is saved, updated Child will also gets saved, updated. No need to explicitly save or update the childrens into the session. In this delete of children will not work. Deletion need to be done explicitly

4) CascadeType.DELETE: This cascade type applies when delete operation performs against the database. In this cascade type, the child will get deleted when a Parent gets deleted from a session. No need to explicitly delete a child from the table.
List<Person> persons = session.createQuery(
  "from Person where" + " person_Id = 2").list();
for (Person person : persons) {
 session.delete(person);
}


5) CascadeType.DELETE_ORPHAN - Deprectaed in Hibernate 4.3.10

6) CascadeType.DETACH - With this cascade type when a Parent is detached Child will also gets detached.

7) CascadeType.EVICT - Deprectaed in Hibernate 4.3.10

8) CascadeType.MERGE - With this cascade type when a Parent is merged Child will also gets detached.

9) CascadeType.PERSIST : It means that save() or persist() operations cascade to Child entities.

Hibernate 4 SessionFactory Example

Hibernate 4 SessionFactory Example

In this post, we will learn how to create org.hibernate.SessionFactory object in Hibernate 4.

Hibernate Version : hibernate-release-4.3.10.Final
JPA Version : JPA 2.1

The hibernate configuration file remains the same. The difference comes while creating the SessionFactory object as the old methods are deprecated in the Hibernate 4.3.10 Final version.


Step 1: Create the Model Annotated Class as shown below
package com.pojo;

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

@Entity
@Table(name = "Person")
public class Person implements java.io.Serializable {

 private Integer id;
 private String name;

 @Id
 @GeneratedValue
 @Column(name = "ID", unique = true, nullable = false)
 public Integer getId() {
  return this.id;
 }

 public void setId(Integer id) {
  this.id = id;
 }

 @Column(name = "NAME", nullable = false)
 public String getName() {
  return this.name;
 }

 public void setName(String name) {
  this.name = name;
 }
}


Step 2: Creating hibernate.cfg file
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

 <session-factory>
  <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
  <property name="hibernate.connection.url">jdbc:mysql://localhost:1000/hibernate4</property>
  <property name="hibernate.connection.username">hibernate4</property>
  <property name="hibernate.connection.password">hibernate4</property>
  <property name="show_sql">true</property>
  <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
  <mapping class="com.pojo.Person" />

 </session-factory>
</hibernate-configuration>




Step 3: Create the HibernateUtil class to create SessionFactory object

In Hibernate 4.3.0 and above versions following classes are deprecated:
1) ServiceRegistryBuilder is deprecated
2) Method buildServiceRegistry() is undefined for the type ServiceRegistryBuilder
3) Method buildSessionFactory() from the type Configuration is deprecated

package com.pojo;

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;

public class Hibernate4Util {
 private static SessionFactory sessionFactory;

 public static SessionFactory getSessionFactory() {
  if (sessionFactory == null) {
   Configuration cfg = new Configuration()
     .configure("hibernate.cfg.xml");
   StandardServiceRegistryBuilder sb = new StandardServiceRegistryBuilder();
   sb.applySettings(cfg.getProperties());
   StandardServiceRegistry standardServiceRegistry = sb.build();
   sessionFactory = cfg.buildSessionFactory(standardServiceRegistry);
  }
  return sessionFactory;
 }
}


Step 4: Hibernate4 Client Test example
package com.pojo;

import java.util.Iterator;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

public class Hibernate4Test {
 public static void main(String[] args) throws Exception {

  SessionFactory sessFact = Hibernate4Util.getSessionFactory();
  Session session = sessFact.getCurrentSession();
  org.hibernate.Transaction tr = session.beginTransaction();

  String strSql = "from Person person";
  Query query = session.createQuery(strSql);
  List lst = query.list();
  for (Iterator it = lst.iterator(); it.hasNext();) {
   Person person = (Person) it.next();
   System.out.println("Hello: " + person.getName());
  }
  tr.commit();
  sessFact.close();
 }
}


How to Configure EhCache in Hibernate

How to Configure EhCache in Hibernate

As seen in the previous post How to configure EhCache in Java, we will see how to configure ehCache as Second level Cache in Hibernate.
ORM Framework like hibernate provides cache mechanism to avoid number of queries made to database, which in turn increase the performance of web application.

Hibernate provides two layers of cache mechanism –
First Level Cache – Works in Session scope, enabled by default.
Second Level Cache – We need to configure the second level cache and it is available in session factory scope.

In this post we will see how to configure the ehCache as Second Level Cache in Hibernate and store/retrieve elements from second level cache.

Let's Start –
1) What is EhCache – As discussed in previous article ehCache is popular open source java cache mechanism which can be used as second level cache in Hibernate. ehCache can be downloaded from - http://www.terracotta.org/products/enterprise-ehcache. Below is maven dependency for ehCache – net.sf.ehcache ehcache 2.9.1

2) Hibernate configuration -
To download the hibernate 3.3.2.GA version from –
http://sourceforge.net/projects/hibernate/files/hibernate3/3.3.2.GA/

3) Configure EhCache in Hibernate
Steps to enable ehcache in Hibernate -

- Enable ehCache in Hibernate. Need to provide the configure in hibernate.cfg.xml
- Configure the entity object either in hbm.xml files or using annotation by choosing appropriate caching strategy
- Enable query caching mechanism
- If needed define the ehcache.xml to over the default values.

Let's understand by example in detail -

Note : In Order to run the application, you need to download the MySql database and should be working and able to connect. Need to create the database and Table by using below commands, which has been used in hibernate.cgf.xml
create database hibernatedemo
create table TRADE(ID int(10),NAME VARCHAR(50));


1. Hibernate Configuration File
In Order to configure ehcache in hibernate need to perform in two steps –
- Enable second level cache in hibernate.cgf.xml
- Specify the second level cache provider.

<?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.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernatedemo</property>
        <property name="hibernate.connection.password">root</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="net.sf.ehcache.configurationResourceName">/ehcache.xml</property>
        <property name="show_sql">true</property>
        <property name="hbm2ddl.auto">create</property>
<!--         <property name="hibernate.cache.use_second_level_cache">true</property> -->
 <property name="hibernate.cache.use_second_level_cache">true</property>
         <property name="hibernate.cache.use_query_cache">true</property>
        <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
        <mapping class="code.desk.entity.DummyTrade"></mapping>
        
    </session-factory>
</hibernate-configuration>




2. Configure Entity Objects
If we are using hbm.xml file then we can configure as –
<class name=" code.desk.entity.DummyTrade " table="TRADE">
    <cache usage="read-write"/>
</class>

If we are using annotation based configuration then we can use the following code snippet–
In Order to define caching strategy we need to put the following statement
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY, region="dummyTrade")

package code.desk.entity;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
 
@Entity (name = "dept")
@Table(name = "TRADE", uniqueConstraints = {
        @UniqueConstraint(columnNames = "ID"),
        @UniqueConstraint(columnNames = "NAME") })
         
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY, region="dummyTrade")
 
public class DummyTrade implements Serializable {
     
    private static final long serialVersionUID = 1L;
 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID", unique = true, nullable = false)
    private Integer id;
     
    @Column(name = "NAME", unique = true, nullable = false, length = 100)
    private String name;
 
    public Integer getId() {
        return id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
}


3. Define the EhCache Configuration File
As per the property defined in hibernate.cgf.xml, need to configure ehcache.xml.
<property name="net.sf.ehcache.configurationResourceName">/ehcache.xml</property>


As Defined in Cache configuration the cache name should be same as region name defined in DummyTrade entity.
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd">
<diskStore path="c:\temp\cache"/>
<cache
    name="dummyTrade"
    maxElementsInMemory="10000"
    eternal="false"
    timeToIdleSeconds="5"
    timeToLiveSeconds="10"
    overflowToDisk="true"
/>
 
</ehcache>


4. Hibernate Utility -
HibernateUtility class use to get the Singleton Instance of SessionFactory.
package code.desk.util;

import java.io.File;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
 
public class HibernateUtility
{
    private static final SessionFactory sessionFactory = buildSessionFactory();
      
    private static SessionFactory buildSessionFactory()
    {
        try
        {
            // Create the SessionFactory from hibernate.cfg.xml
            return new AnnotationConfiguration().configure(new File("hibernate.cgf.xml")).buildSessionFactory();
        }
        catch (Throwable ex) {
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }
  
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
  
    public static void shutdown() {
        // Close caches and connection pools
        getSessionFactory().close();
    }
}


5. Finally Test the Functionality -
In order to understand better I kept example easy and simple. Object stored in first level cache associated with session but objects stored in second level cache remains beyond the session as well.
In the below example, first we load the entity, which triggers database call and store it into the first level cache and second level cache.
When try to load the same entity again, it first look into the first level cache and if found it returns, this doesn't make any database call.
Now in order to test second level cache, we close the first session, which make sure the entity is not getting load from first level cache. Now again create the another session and try to load the entity, you can see the output, it will load from the second level cache and doesn't make the call to database.

Below is the code snippet –
package code.desk.test;

import org.hibernate.Session;
import org.hibernate.stat.Statistics;

import code.desk.entity.DummyTrade;
import code.desk.util.HibernateUtility;

public class TestHibernateEhcacheMain
{  
    public static void main(String[] args)
    {
        insertDataToDB();
        Statistics statistics = HibernateUtility.getSessionFactory().getStatistics();
        try
        {
         // Enable the hibernate statics 
         System.out.println("Is statics enabled "+statistics.isStatisticsEnabled());
         statistics.setStatisticsEnabled(true);
         System.out.println("Is statics enabled "+statistics.isStatisticsEnabled());
            //Open the hibernate session
            Session session = HibernateUtility.getSessionFactory().openSession();
            session.beginTransaction();
             
            //fetch the department entity from database first time
            DummyTrade department = (DummyTrade) session.load(DummyTrade.class, new Integer(1));
            System.out.println(department.getName());
             
            //fetch the department entity again; Fetched from first level cache
            department = (DummyTrade) session.load(DummyTrade.class, new Integer(1));
            System.out.println(department.getName());
            //Let's close the session
            
            session.getTransaction().commit();
            session.close();
            
             
            //Try to get department in new session
            Session anotherSession = HibernateUtility.getSessionFactory().openSession();
            anotherSession.beginTransaction();
             
            //Here entity is already in second level cache so no database query will be hit
            department = (DummyTrade) anotherSession.load(DummyTrade.class, new Integer(1));
            System.out.println(department.getName());
            
            
            anotherSession.getTransaction().commit();
            anotherSession.close();
        }
        finally
        {
            
   System.out.println(statistics.getEntityFetchCount()); //Prints 1
            System.out.println(statistics.getSecondLevelCacheHitCount()); //Prints 1
             
            HibernateUtility.shutdown();
        }
    }
     
    private static void insertDataToDB()
    {
        Session session = HibernateUtility.getSessionFactory().openSession();
        session.beginTransaction();
         
        DummyTrade department = new DummyTrade();
        department.setName("Human Resource");
         
        session.save(department);
        session.getTransaction().commit();
        session.close();
    }
}


This post is written by
Soumitra Pathak - Linkedin, Facebook

He is a freelance writer, loves to explore latest features in Java technology.

Hibernate ignore column mapping annotation

Hibernate ignore column mapping annotation

In hibernate pojo, annotations are used for each property or their corresponding getter. We may require to add some property or method which we may want hibernate to ignore at runtime.

Say, for example there are four fields in Person Hibernate Pojo :
1) name
2) age
3) dateOfBirth
4) address

Consider a method isAbove18() is there which checks if date of birth is greater than 18 years from current date in a POJO.

public boolean isAbove18() {
 ...
}


Hibernate will complain, "above18" property is not available.

To resolve this, one can use "@Transient" annotation of JPA to inform Hibernate to ignore this property/method at runtime.

@Transient
public boolean isAbove18() {
 ...
}

@Transient
private String address;


FetchType LAZY and EAGER Hibernate

FetchType LAZY and EAGER Hibernate

In Hibernate, to define the relationships between two table we use following annotations :
1) @OneToOne
2) @ManyToOne
3) @ManyToMany
4) @OneToMany
from the javax.persistence package

When we load any entity from the database using the Hibernate session, there are two FetchType strategies we can use that belongs to javax.persistence.FetchType class :
1) LAZY - As the name suggests, relation entity that uses this FetchType will be lazily loaded i.e. it will be loaded from the database on demand. When we load the entity from the database it will not load the relationship entities. As an when required, the relationship entity can be called using the getter method.

2) EAGER - As the name suggests, relationship entity that uses this FetchType will be loaded as soon as the object entity is loaded from the database.

If you do not mention FetchType for relationship entity, hibernate will by default take that as FetchType LAZY.

Consider an example of an Insurance company which has set of employees in each geographical unit. We can create hibernate entity for this as shown below:

Insurance.java
package com.entity;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "Insurance")
@NamedQueries({ @NamedQuery(name = "getInsuranceForLocation", query = "select t from Insurance t where t.location=?") })
public class Insurance {

    @Id
    @Column(name = "accountNumber")
    private String location;
    
    @OneToMany(fetch = FetchType.EAGER)
    private List<Employee> employees;

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public List<Employee> getEmployees() {
        return employees;
    }

    public void setEmployees(List<Employee> employees) {
        this.employees = employees;
    }
}


Employee.java


package com.entity;

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

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

    @Id
    @Column(name = "employeeId")
    private String employeeId;

    public String getEmployeeId() {
        return employeeId;
    }

    public void setEmployeeId(String employeeId) {
        this.employeeId = employeeId;
    }
}


As shown above, as soon as we fire the getInsuranceForLocation Naming Query, Insurance object will be loaded from DB, it will also fetch all the employees working in that particular Geograplical Location since the relationship @OneToMany is using FetchType as EAGER.

If the FetchType is changed to LAZY, then fire the getInsuranceForLocation Naming Query, it will not load the Employee Collection object, but it will load the collection of Employees when the getter method "getEmployees()" is explicitly called.

Hibernate Named Query Annotations example

Named Query can be used in hibernate through Annotation using below classes:
1) import javax.persistence.NamedQueries;
2) import javax.persistence.NamedQuery;

NamedQueries consists of list of NamedQuery which holds each query.

Basic example of NamedQueries consisting of single Named query as shown below
@NamedQueries({ @NamedQuery(name = "getData", query = "select t from CLASS_NAME t") })

CLASS_NAME - Refers to class in which you are using the NamedQuery.

Hibernate One to Many annotation using Named Query

Hibernate One to Many annotation using Named Query In this example, I have OneToMany releationship between two tables without Join table using annotation.
Table 1 - Person
Table 2 - Address

One Person can have multiple address. Relationship between the two tables is Address table has foreign key "personIdFk" which is mapped by "personId" of Person table.

1) Configure the datasource - This is configured in the spring application context xml file. Configure the bean for datasource using class org.springframework.jdbc.datasource.DriverManagerDataSource. The class can be found in jar spring-jdbc-2.0.7.jar
Load Database Configuration from Properties file

Hibernate annotation example with Spring

Hibernate annotation example with Spring

The web application to be created using Struts Spring and Hibernate can be configured in 6 easy steps. This configuration is an example to configure hibernate using .hbm files using the HibernateDaoSupport as shown below:
1) Configure the datasource - This is configured in the spring application context xml file. Configure the bean for datasource using class org.springframework.jdbc.datasource.DriverManagerDataSource. The class can be found in jar spring-jdbc-2.0.7.jar
Load Database Configuration from Properties file

Integrate Struts Spring Hibernate web application

Integrate Struts Spring Hibernate web application

The web application to be created using Struts Spring and Hibernate can be configured in 6 easy steps. This configuration is an example to configure hibernate using .hbm files using the HibernateDaoSupport as shown below:
1) Load the Spring application context xml file in struts-config - This can be achieved using the Spring pugin for struts org.springframework.web.struts.ContextLoaderPlugIn class. The jar in which you can find this class is org.springframework.web.struts-3.0.1.RELEASE.jar

<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">  
 <set-property property="contextConfigLocation"  
 value="/WEB-INF/springconfig/applicationContext.xml"/>  
 </plug-in>