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