In this post, We will learn about Spring and Hibernate Declarative Transaction Management Example using a Demo Project.
In hibernate framework, we usually provide all the database information in the hibernate.cfg.xml file.
But when we integrate the hibernate application with spring, we really don’t need to create the hibernate.cfg.xml file. We can configure all the information in the applicationContext.xml file.
pom.xml
We need to add Spring, Hibernate and MySQL dependencies in Maven pom.xml file
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 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.kkhindigyan.org</groupId> <artifactId>SpringAndHibernateAnnotationbasedTransactionManagement</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <org.springframework.version>5.2.13.RELEASE</org.springframework.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.23</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.4.30.Final</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.2.13.RELEASE</version> </dependency> </dependencies> </project> |
Employee.java
Employee entity class to store employee data
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 |
package com.kkhindigyan.org.model; 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 org.hibernate.annotations.DynamicUpdate; @Entity @Table(name = "employee_table") @DynamicUpdate public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "employee_id") private Integer employeeId; @Column(name = "employee_name") private String employeeName; @Column(name = "email") private String email; @Column(name = "gender") private String gender; @Column(name = "salary") private Double salary; public Integer getEmployeeId() { return employeeId; } public void setEmployeeId(Integer employeeId) { this.employeeId = employeeId; } public String getEmployeeName() { return employeeName; } public void setEmployeeName(String employeeName) { this.employeeName = employeeName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public Double getSalary() { return salary; } public void setSalary(Double salary) { this.salary = salary; } @Override public String toString() { return "Employee [employeeId=" + employeeId + ", employeeName=" + employeeName + ", email=" + email + ", gender=" + gender + ", salary=" + salary + "]"; } } |
EmployeeService.java
Employee Service Interface
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package com.kkhindigyan.org.service; import java.util.List; import com.kkhindigyan.org.model.Employee; public interface EmployeeService { public abstract void createEmployee(Employee employee); public abstract Employee getEmployeeById(Integer employeeId); public abstract List<Employee> getAllEmployees(); public abstract void updateEmployeeEmailById(String newEmail,Integer employeeId); public abstract void deleteEmployeeById(Integer employeeId); } |
EmployeeServiceImpl.java
Employee Service Implementation class
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 |
package com.kkhindigyan.org.service; import java.util.List; import com.kkhindigyan.org.dao.EmployeeDao; import com.kkhindigyan.org.model.Employee; public class EmployeeServiceImpl implements EmployeeService { private EmployeeDao employeeDao; public EmployeeDao getEmployeeDao() { return employeeDao; } public void setEmployeeDao(EmployeeDao employeeDao) { this.employeeDao = employeeDao; } @Override public void createEmployee(Employee employee) { getEmployeeDao().createEmployee(employee); } @Override public Employee getEmployeeById(Integer employeeId) { return getEmployeeDao().fetchEmployeeById(employeeId); } @Override public List<Employee> getAllEmployees() { return getEmployeeDao().fetchAllEmployees(); } @Override public void updateEmployeeEmailById(String newEmail, Integer employeeId) { getEmployeeDao().updateEmployeeEmailById(newEmail, employeeId); } @Override public void deleteEmployeeById(Integer employeeId) { getEmployeeDao().deleteEmployeeById(employeeId); } } |
EmployeeDao.java
Employee DAO(Data Access Object) Interface
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package com.kkhindigyan.org.dao; import java.util.List; import com.kkhindigyan.org.model.Employee; public interface EmployeeDao { public abstract void createEmployee(Employee employee); public abstract Employee fetchEmployeeById(Integer employeeId); public abstract List<Employee> fetchAllEmployees(); public abstract void updateEmployeeEmailById(String newEmail,Integer employeeId); public abstract void deleteEmployeeById(Integer employeeId); } |
EmployeeDaoImpl.java
Employee DAO(Data Access Object) Interface implementation class to perform CRUD operations with MySQL database.
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 |
package com.kkhindigyan.org.dao; import java.util.List; import org.hibernate.criterion.DetachedCriteria; import org.springframework.orm.hibernate5.HibernateTemplate; import com.kkhindigyan.org.model.Employee; public class EmployeeDaoImpl implements EmployeeDao { private HibernateTemplate hibernateTemplate; public void setHibernateTemplate(HibernateTemplate hibernateTemplate) { this.hibernateTemplate = hibernateTemplate; } public HibernateTemplate getHibernateTemplate() { return hibernateTemplate; } @Override public void createEmployee(Employee employee) { getHibernateTemplate().persist(employee); } @Override public Employee fetchEmployeeById(Integer employeeId) { return getHibernateTemplate().get(Employee.class, employeeId); } @Override public List<Employee> fetchAllEmployees() { DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Employee.class); List<Employee> employeeList = (List<Employee>) getHibernateTemplate().findByCriteria(detachedCriteria); return employeeList; } @Override public void updateEmployeeEmailById(String newEmail, Integer employeeId) { Employee employee = getHibernateTemplate().get(Employee.class, employeeId); employee.setEmail(newEmail); getHibernateTemplate().update(employee); } @Override public void deleteEmployeeById(Integer employeeId) { Employee employee = getHibernateTemplate().get(Employee.class, employeeId); if(employee == null) { System.out.println("Entity does not Exist with ID = "+employeeId +" which you want to delete"); }else { getHibernateTemplate().delete(employee); } } } |
In this config file, we are providing all the information of the database in the DriverManagerDataSource object. This object is used in the LocalSessionFactoryBean class object, containing some other information such as packagesToScan and hibernateProperties. The object of LocalSessionFactoryBean class is used to inject in org.springframework.orm.hibernate5.HibernateTemplate in EmployeeDaoImpl class using setter based dependency injection
We usually manage transactions on the service layer. Here We have used Spring AOP Advice to handle the transaction. AOP Advice refers hibernateTransactionManager internally to manage the transaction. Finally, We have provided the Service layer methods for transaction handling there we have the option to provide transaction attributes like isolation & propagation levels, timeout,readOnly and rollbackFor etc..
1 2 3 4 5 6 7 8 |
<tx:advice id="txAdvice" transaction-manager="hibernateTransactionManager"> <tx:attributes> <tx:method name="createEmployee" isolation="READ_COMMITTED" propagation="REQUIRED" /> <tx:method name="updateEmployeeEmailById" isolation="READ_COMMITTED" propagation="REQUIRED"/> <tx:method name="deleteEmployeeById"/> </tx:attributes> </tx:advice> |
We can also Manage transactions using annotations rather than using XML Declarative transaction management for that, we can use the below annotation either at the service class or method level with some optional attributes.
1 2 |
@Transactional(isolation=Isolation.READ_COMMITTED,propagation = Propagation.REQUIRED,timeout=100, readOnly=false,rollbackFor=Exception.class) |
applicationContext.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 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 |
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="employeeServiceImpl" class="com.kkhindigyan.org.service.EmployeeServiceImpl"> <property name="employeeDao" ref="employeeDaoImpl"></property> </bean> <bean id="employeeDaoImpl" class="com.kkhindigyan.org.dao.EmployeeDaoImpl"> <property name="hibernateTemplate" ref="hibernateTemplate"></property> </bean> <bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate"> <property name="sessionFactory" ref="sessionFactory"></property> <property name="checkWriteOperations" value="false"></property> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="packagesToScan"> <array> <value>com.kkhindigyan.org.model</value> </array> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> <prop key="hibernate.hbm2ddl.auto">create</prop> </props> </property> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <constructor-arg name="url" value="jdbc:mysql://localhost:3306/test"></constructor-arg> <constructor-arg name="username" value="root"></constructor-arg> <constructor-arg name="password" value="root"></constructor-arg> </bean> <tx:advice id="txAdvice" transaction-manager="hibernateTransactionManager"> <tx:attributes> <tx:method name="createEmployee" isolation="READ_COMMITTED" propagation="REQUIRED" /> <tx:method name="updateEmployeeEmailById" isolation="READ_COMMITTED" propagation="REQUIRED"/> <tx:method name="deleteEmployeeById"/> </tx:attributes> </tx:advice> <aop:config proxy-target-class="true"> <aop:pointcut expression="execution(* com.kkhindigyan.org.service.EmployeeServiceImpl.*(..))" id="selectAll" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="selectAll" /> </aop:config> <bean id="hibernateTransactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> <property name="dataSource" ref="dataSource"></property> </bean> </beans> |
ClientTest.java
This ClientTest class gets the bean from the applicationContext.xml file and calls the different methods of EmployeeService to perform CRUD operation with MySQL database.
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 |
package com.kkhindigyan.org.client; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.kkhindigyan.org.model.Employee; import com.kkhindigyan.org.service.EmployeeService; import com.kkhindigyan.org.service.EmployeeServiceImpl; public class ClientTest { public static void main(String[] args) { AbstractApplicationContext ctx = null; try { ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); EmployeeService employeeService = ctx.getBean(EmployeeServiceImpl.class); createEmployee(employeeService); getEmployeeById(employeeService); fetchAllEmployeesInfo(employeeService); employeeService.deleteEmployeeById(2); } catch (Exception e) { e.printStackTrace(); }finally { if(ctx != null) ctx.close(); } } private static void fetchAllEmployeesInfo(EmployeeService employeeService) { employeeService.getAllEmployees().forEach(System.out::println); } private static void getEmployeeById(EmployeeService employeeService) { Employee employee = employeeService.getEmployeeById(1); System.out.println(employee); } private static void createEmployee(EmployeeService employeeService) { Employee employee = getEmployee() ; employeeService.createEmployee(employee); } private static Employee getEmployee() { Employee employee = new Employee(); employee.setEmployeeName("KK"); employee.setGender("Male"); employee.setSalary(95000.00); return employee; } } |
If you run ClientTest.java as Java Application then it will give the below 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 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 |
Jun 19, 2021 9:01:56 PM org.hibernate.Version logVersion INFO: HHH000412: Hibernate ORM core version 5.4.30.Final Jun 19, 2021 9:01:56 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit> INFO: HCANN000001: Hibernate Commons Annotations {5.1.2.Final} Jun 19, 2021 9:01:57 PM org.hibernate.dialect.Dialect <init> INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect Hibernate: drop table if exists employee_table Hibernate: create table employee_table ( employee_id integer not null auto_increment, email varchar(255), employee_name varchar(255), gender varchar(255), salary double precision, primary key (employee_id) ) engine=MyISAM Jun 19, 2021 9:01:57 PM org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] Hibernate: insert into employee_table (email, employee_name, gender, salary) values (?, ?, ?, ?) Hibernate: select employee0_.employee_id as employee1_0_0_, employee0_.email as email2_0_0_, employee0_.employee_name as employee3_0_0_, employee0_.gender as gender4_0_0_, employee0_.salary as salary5_0_0_ from employee_table employee0_ where employee0_.employee_id=? Employee [employeeId=1, employeeName=KK, email=kk.m@gmail.com, gender=Male, salary=95000.0] Hibernate: select this_.employee_id as employee1_0_0_, this_.email as email2_0_0_, this_.employee_name as employee3_0_0_, this_.gender as gender4_0_0_, this_.salary as salary5_0_0_ from employee_table this_ Employee [employeeId=1, employeeName=KK, email=kk.m@gmail.com, gender=Male, salary=95000.0] Hibernate: select employee0_.employee_id as employee1_0_0_, employee0_.email as email2_0_0_, employee0_.employee_name as employee3_0_0_, employee0_.gender as gender4_0_0_, employee0_.salary as salary5_0_0_ from employee_table employee0_ where employee0_.employee_id=? Hibernate: update employee_table set email=? where employee_id=? Hibernate: select employee0_.employee_id as employee1_0_0_, employee0_.email as email2_0_0_, employee0_.employee_name as employee3_0_0_, employee0_.gender as gender4_0_0_, employee0_.salary as salary5_0_0_ from employee_table employee0_ where employee0_.employee_id=? Entity does not Exist with ID = 2 which you want to delete |
MySQL Database Screen Shot After running ClientTest:
That’s all about Spring and Hibernate Declarative Transaction Management Example
You May Also Like:
Spring JDBC Integration Example
Spring JDBC Annotation Example
Spring with Jdbc java based configuration example
Spring JDBC NamedParameterJdbcTemplate Example
How to call stored procedures in the Spring Framework?
Spring 5 and Hibernate 5 integration CRUD Example
Spring HibernateTempate Example
If you have any feedback or suggestion please feel free to drop in below comment box.