Thursday, 20 October 2016

1. Hibernate Spring Integration Example

Hibernate is most popular ORM framework and Spring is widely used J2EE framework so combination of Spring with Hibernate is used lot in many enterprise level applications. Hibernate is JPA provider with lot of addition of added functionalities.

In this series of tutorials, we will be exploring different functionalities of Hibernate and will see how Spring makes it more easier to configure and use Hibernate.

Artifacts used in these tutorials are,

Spring - 4.3.3.RELEASE
Hibernate - 4.3.11.Final

First look at final project structure. We will look at each of these one by one.


POM.xml for dependencies is as below,

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 <properties>
  <springframework.version>4.3.3.RELEASE</springframework.version>
 </properties>
 <dependencies>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-core</artifactId>
   <version>${springframework.version}</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context-support</artifactId>
   <version>${springframework.version}</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-jdbc</artifactId>
   <version>${springframework.version}</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-orm</artifactId>
   <version>${springframework.version}</version>
  </dependency>
  <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-core</artifactId>
   <version>4.3.11.Final</version>
  </dependency>
  <dependency>
   <groupId>postgresql</groupId>
   <artifactId>postgresql</artifactId>
   <version>9.1-901-1.jdbc4</version>
  </dependency>
 </dependencies>

Dependency for PostgreSQL is also added as we will be using PostgreSQL database for this tutorial.

Now, first we will create entity class 'Employee' using JPA annotations as hibernate provides JPA implementation.

Employee.java
1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
package in.blogspot.ashish4java.employeesystem.model;

import java.io.Serializable;
import java.util.Date;

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

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

 /**
  * 
  */
 private static final long serialVersionUID = -7778913816135373156L;
 private String firstName;
 private String lastName;

 @Id
 @GeneratedValue
 private int employeeId;

 private Date joiningDate;
 private Date leavingDate;

 private String designation;

 public String getFirstName() {
  return firstName;
 }

 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }

 public String getLastName() {
  return lastName;
 }

 public void setLastName(String lastName) {
  this.lastName = lastName;
 }

 public int getEmployeeId() {
  return employeeId;
 }

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

 public Date getJoiningDate() {
  return joiningDate;
 }

 public void setJoiningDate(Date joiningDate) {
  this.joiningDate = joiningDate;
 }

 public Date getLeavingDate() {
  return leavingDate;
 }

 public void setLeavingDate(Date leavingDate) {
  this.leavingDate = leavingDate;
 }

 public String getDesignation() {
  return designation;
 }

 public void setDesignation(String designation) {
  this.designation = designation;
 }

 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + employeeId;
  return result;
 }

 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  Employee other = (Employee) obj;
  if (employeeId != other.employeeId)
   return false;
  return true;
 }

 @Override
 public String toString() {
  return "Employee [firstName=" + firstName + ", lastName=" + lastName + ", employeeId=" + employeeId
    + ", joiningDate=" + joiningDate + ", leavingDate=" + leavingDate + ", designation=" + designation
    + "]";
 }

}

Make Employee entity serializable. EmployeeId field is primary key and value for that will be automatically generated by Hibernate.

DAO Classes
Next, we will create DAO classes for creating and fetching this entity from database. Create, Delete, Update and Get - these will be main operations in DAO class which we will implement.

Let's create interface first for DAO class to define this contract.

EmployeeDao.java
1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package in.blogspot.ashish4java.employeesystem.dao;

import in.blogspot.ashish4java.employeesystem.model.Employee;

public interface EmployeeDao {

 void createEmployee(Employee emp);

 void updateEmployee(Employee emp);

 void deleteEmployee(Employee emp);

 Employee getEmployee(int employeeId);

}

Create abstract DAO class and provide implementation of few of common methods,

AbstractDao.java
1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package in.blogspot.ashish4java.employeesystem.dao;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;

public class AbstractDao {

 @Autowired
 SessionFactory sessionFactory;

 protected Session getsession() {
  return sessionFactory.openSession();
 }

 public void createEntity(Object entity) {
  Session session = getsession();
  session.beginTransaction();
  session.save(entity);
  session.getTransaction().commit();
 }

 public void updateEntity(Object entity) {
  Session session = getsession();
  session.beginTransaction();
  session.update(entity);
  session.getTransaction().commit();
 }

 public void deleteEntity(Object entity) {
  Session session = getsession();
  session.beginTransaction();
  session.delete(entity);
  session.getTransaction().commit();
 }

}

Note: SessionFactoy will be autowired by Spring and then Session object is given by this factory using openSession() method which opens new session everytime. This session needs to be closed everytime once transaction is over as session is not thread safe. If you note, there is lot of boilerplate code in these DAO methods like getting session, beginning transaction, performing operation and then committing transaction. In one of future tutorial, we will see how to get rid of this using Spring provided transaction management.

Let's implement remaining method from EmployeeDao interface

EmployeeDaoImpl.java
1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package in.blogspot.ashish4java.employeesystem.dao;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

import in.blogspot.ashish4java.employeesystem.model.Employee;

@Repository
public class EmployeeDaoImpl extends AbstractDao implements EmployeeDao {

 @Override
 public void createEmployee(Employee emp) {
  createEntity(emp);
 }

 @Override
 public void updateEmployee(Employee emp) {
  updateEntity(emp);
 }

 @Override
 public void deleteEmployee(Employee emp) {
  deleteEntity(emp);
 }

 @Override
 public Employee getEmployee(int employeeId) {
  Session session = getsession();
  Criteria criteria = session.createCriteria(Employee.class).add(Restrictions.eq("employeeId", employeeId));
  return (Employee) criteria.uniqueResult();
 }

}

Notice we have used Criteria then putting Restriction on employeeId to fetch particular employee from table. There are different ways to implement this in hibernate and this is one of them.

Service Class implementation

EmployeeService.java
1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package in.blogspot.ashish4java.employeesystem.service;

import in.blogspot.ashish4java.employeesystem.model.Employee;

public interface EmployeeService {

 void createEmployee(Employee emp);

 void updateEmployee(Employee emp);

 void deleteEmployee(Employee emp);

 Employee getEmployee(int employeeId);

}

EmployeeServiceImple.java

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package in.blogspot.ashish4java.employeesystem.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import in.blogspot.ashish4java.employeesystem.dao.EmployeeDao;
import in.blogspot.ashish4java.employeesystem.model.Employee;

@Service ("empService")
public class EmployeeServiceImpl implements EmployeeService {

 @Autowired
 EmployeeDao employeeDao;

 @Override
 public void createEmployee(Employee emp) {
  employeeDao.createEmployee(emp);

 }

 @Override
 public void updateEmployee(Employee emp) {
  employeeDao.updateEmployee(emp);
 }

 @Override
 public void deleteEmployee(Employee emp) {
  employeeDao.deleteEmployee(emp);
 }

 @Override
 public Employee getEmployee(int employeeId) {
  return employeeDao.getEmployee(employeeId);
 }
}

Spring Bean Configuration XML

Spring.xml

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
 xmlns:jee="http://www.springframework.org/schema/jee" xmlns:util="http://www.springframework.org/schema/util"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
  http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.3.xsd
  http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">

 <context:component-scan base-package="in.blogspot.ashish4java.employeesystem" />

 <bean id="myDataSource"
  class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName" value="org.postgresql.Driver" />
  <property name="url" value="jdbc:postgresql://localhost:5432/rmsystem" />
  <property name="username" value="postgres" />
  <property name="password" value="password" />
 </bean>

 <bean id="sessionFactory"
  class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
  <property name="packagesToScan" value="in.blogspot.ashish4java.employeesystem.model"></property>
  <property name="dataSource" ref="myDataSource" />
  <property name="hibernateProperties">
   <props>
    <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL9Dialect</prop>
    <prop key="hibernate.show_sql">true</prop>
    <prop key="hibernate.hbm2ddl.auto">create</prop>
    <prop key="current_session_context_class">thread</prop>
    <prop key="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</prop>
    <prop key="hibernate.autocommit">false</prop>
    <prop key="hibernate.format_sql">true</prop>
   </props>
  </property>
 </bean>
</beans>

We have created datasource first and then passed that datasource to create SessionFactory. Spring provides implementation of SessionFactory with "org.springframework.orm.hibernate4.LocalSessionFactoryBean"

Now, remaining part is to implement client to demonstrate this complete example.

I have created one helper class which will give set Employee object which needs to be persisted to database. This utility class is not necessary and can be ignored.

EmployeeHelper.java
1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package in.blogspot.ashish4java.employeesystem.utils;

import java.util.Random;

import org.springframework.stereotype.Component;

import in.blogspot.ashish4java.employeesystem.model.Employee;

@Component("empHelper")
public class EmployeeHelper {

 private static final String designation = "Full Stack Java developer";

 public Employee CreateEmployeeOnRequest() {
  Random r = new Random();
  Employee emp = new Employee();
  emp.setFirstName("ABC" + r.nextInt(100));
  emp.setLastName("XYZ" + r.nextInt(100));
  emp.setDesignation(designation);
  return emp;
 }

}

MainClient.java
1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package in.blogspot.ashish4java.employeesystem.client;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import in.blogspot.ashish4java.employeesystem.model.Employee;
import in.blogspot.ashish4java.employeesystem.service.EmployeeService;
import in.blogspot.ashish4java.employeesystem.utils.EmployeeHelper;

public class MainClient {

 public static void main(String[] args) {
  ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
  EmployeeHelper empHelper = (EmployeeHelper) context.getBean("empHelper");
  Employee emp = empHelper.CreateEmployeeOnRequest();

  EmployeeService service = (EmployeeService) context.getBean("empService");

  // Cretae Employee
  service.createEmployee(emp);

  // Get Employee Details for ID = 1
  Employee employee = service.getEmployee(1);

  System.out.println();
  System.out.println(employee);

  context.close();

 }

}

Make sure, PostgrSQL database is up and running. Now, let's execute this client and see the output.

Output
1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
INFO: HHH000227: Running hbm2ddl schema export
Hibernate: 
    drop table EMPLOYEE cascade
Hibernate: 
    drop sequence hibernate_sequence
Hibernate: 
    create table EMPLOYEE (
        employeeId int4 not null,
        designation varchar(255),
        firstName varchar(255),
        joiningDate timestamp,
        lastName varchar(255),
        leavingDate timestamp,
        primary key (employeeId)
    )
Hibernate: 
    create sequence hibernate_sequence
Oct 20, 2016 9:46:15 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: HHH000230: Schema export complete
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    insert 
    into
        EMPLOYEE
        (designation, firstName, joiningDate, lastName, leavingDate, employeeId) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    select
        this_.employeeId as employee1_0_0_,
        this_.designation as designat2_0_0_,
        this_.firstName as firstNam3_0_0_,
        this_.joiningDate as joiningD4_0_0_,
        this_.lastName as lastName5_0_0_,
        this_.leavingDate as leavingD6_0_0_ 
    from
        EMPLOYEE this_ 
    where
        this_.employeeId=?

Employee [firstName=ABC66, lastName=XYZ53, employeeId=1, joiningDate=null, leavingDate=null, designation=Full Stack Java developer]
Oct 20, 2016 9:46:16 AM org.springframework.context.support.ClassPathXmlApplicationContext doClose
INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContext@133ddba: startup date [Thu Oct 20 09:46:07 IST 2016]; root of context hierarchy

Output clearly shows, it has created Employee table first along with sequence for primary key when SessionFactory was created. Then client execution, it inserted one record in that table as we expected and same record was fetched.

In next tutorial, we will see few more operations like how to fetch all employees from table and how to fetch sub set of employees based on where clause.

No comments:

Post a Comment