Spring Boot声明式事务管理示例
Posted 独孤文彬
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Boot声明式事务管理示例相关的知识,希望对你有一定的参考价值。
视频讲解地址:(预留:待上传……)
让我们开始吧:
什么是数据库事务?
数据库事务是访问并可能修改数据库内容的单个逻辑工作单元。
让我们检查一下mysql数据库:
- 为mysql数据库打开两个单独的窗口
- 在一个mysql窗口中,创建一个名为test的数据库,并在‘s其中创建一个名为employee的表
create database test;
create table employee(id varchar(10), name varchar(10));
- 默认情况下,事务是针对mysql数据库自动提交的。 我们将使用以下命令禁用自动提交:
SET autocommit = 0;
- 在第一个mysql窗口中,使用以下插入命令-如果现在使用第二个mysql窗口,请对employee表进行选择,我们将看不到任何记录。这是因为事务仍未在第一个mysql窗口中提交。
- 现在,我们在第一个MySQL命令中使用commit命令。如果现在使用第二个mysql窗口,请选择employee表,我们将看到两条记录
应用程序中的事务:
现在让我们将应用程序事务用于Spring Boot JDBC项目。
我们将开发一个用于员工管理的Spring Boot + JDBC项目。它将有3个服务
- EmployeeService-服务将执行员工操作
- HealthInsuranceService-该服务将执行员工健康保险业务
- OrganizationService-服务将执行组织级别的操作,例如员工加入和退出。它利用EmployeeService和HealthInsuranceService
OrganizationService员工加入工作流程
OrganizationService员工退出工作流程
应用程序事务是应用程序操作的序列,被应用程序视为单个逻辑单元。对于我们的应用程序,joinOrganization方法将被视为一项完整的事务。 joinOrganization由两个动作组成-
- 持久化员工信息
- 持久化健康保险信息
如果由于任何原因上述任何一个操作失败,则另一个操作也应回滚。因此,如果插入了“员工信息”,但假设由于某些原因而导致HealthInsurance失败,则还应该回滚“员工信息”。这意味着逻辑工作单元是全部或全部。 exitOrganization方法的情况与此类似,它将被视为一个工作单元。
最初,我们将不使用任何事务管理。默认情况下,spring boot事务是自动提交。但这不是一个好习惯,我们将在下一节中了解原因。
程序细节展示
1、工程结构
2、Pom文件的内容:
<?xml version="1.0" encoding="UTF-8"?>
<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.javainuse</groupId>
<artifactId>boot-jdbc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>boot-jdbc</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3、修改配置文件:(替换成自己的数据库服务器的ip,用户名和密码)
spring.datasource.url=jdbc:mysql://数据库服务器的ip/bootdb?createDatabaseIfNotExist=true&autoReconnect=true&useSSL=false
spring.datasource.username= 数据库用户名
spring.datasource.password= 密码
spring.datasource.platform=mysql
spring.datasource.initialization-mode=always
logging.level.org.springframework=DEBUG
4、这是初始化脚本,由Spring Boot JDBC-开始运行
DROP TABLE IF EXISTS employee;
DROP TABLE IF EXISTS employeeHealthInsurance;
CREATE TABLE employee (
empId VARCHAR(10) NOT NULL,
empName VARCHAR(100) NOT NULL
);
CREATE TABLE employeeHealthInsurance (
empId VARCHAR(10) NOT NULL,
healthInsuranceSchemeName VARCHAR(100) NOT NULL,
coverageAmount VARCHAR(100) NOT NULL
);
5、定义Model类Employee,它将代表Employee详细信息
package com.javainuse.model;
public class Employee
private String empId;
private String empName;
public String getEmpId()
return empId;
public void setEmpId(String empId)
this.empId = empId;
public String getEmpName()
return empName;
public void setEmpName(String empName)
this.empName = empName;
@Override
public String toString()
return "Employee [empId=" + empId + ", empName=" + empName + "]";
6、创建用于执行Employee操作的EmployeeDAO接口,如下所示:
package com.javainuse.dao;
import com.javainuse.model.Employee;
public interface EmployeeDao
void insertEmployee(Employee cus);
void deleteEmployeeById(String empid);
7、创建实现EmployeeDAO接口的EmployeeDAOImpl,如下所示。
Spring Boot将在类路径和mysql上检测spring-jdbc,并将自动为我们创建一个数据源和一个JdbcTemplate。因为这样的基础结构现在可用,并且我们没有专用的配置,所以还将为我们创建一个DataSourceTransactionManager。
package com.javainuse.dao.impl;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Repository;
import com.javainuse.dao.EmployeeDao;
import com.javainuse.model.Employee;
@Repository
public class EmployeeDaoImpl extends JdbcDaoSupport implements EmployeeDao
@Autowired
DataSource dataSource;
@PostConstruct
private void initialize()
setDataSource(dataSource);
@Override
public void insertEmployee(Employee emp)
String sql = "INSERT INTO employee " + "(empId, empName) VALUES (?, ?)";
getJdbcTemplate().update(sql, new Object[] emp.getEmpId(), emp.getEmpName() );
@Override
public void deleteEmployeeById(String empid)
String sql = "DELETE FROM employee WHERE empId = ?";
getJdbcTemplate().update(sql, new Object[] empid );
8、定义Model类EmployeeHealthInsurance,它将代表Employee Health Insurance详细信息-
package com.javainuse.model;
public class EmployeeHealthInsurance
private String empId;
private String healthInsuranceSchemeName;
private int coverageAmount;
public String getEmpId()
return empId;
public void setEmpId(String empId)
this.empId = empId;
public String getHealthInsuranceSchemeName()
return healthInsuranceSchemeName;
public void setHealthInsuranceSchemeName(String healthInsuranceSchemeName)
this.healthInsuranceSchemeName = healthInsuranceSchemeName;
public int getCoverageAmount()
return coverageAmount;
public void setCoverageAmount(int coverageAmount)
this.coverageAmount = coverageAmount;
9、创建执行以下医疗保险业务的HealthInsuranceDao-
package com.javainuse.dao;
import com.javainuse.model.EmployeeHealthInsurance;
public interface HealthInsuranceDao
void registerEmployeeHealthInsurance(EmployeeHealthInsurance employeeHealthInsurance);
void deleteEmployeeHealthInsuranceById(String empid);
10、创建实现HealthInsuranceDao的EmployeeHealthInsuranceDAOImpl,如下所示:
package com.javainuse.dao.impl;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Repository;
import com.javainuse.dao.HealthInsuranceDao;
import com.javainuse.model.EmployeeHealthInsurance;
@Repository
public class HealthInsuranceDaoImpl extends JdbcDaoSupport implements HealthInsuranceDao
@Autowired
DataSource dataSource;
@PostConstruct
private void initialize()
setDataSource(dataSource);
@Override
public void registerEmployeeHealthInsurance(EmployeeHealthInsurance emp)
String sql = "INSERT INTO employeeHealthInsurance "
+ "(empId, healthInsuranceSchemeName, coverageAmount) VALUES (?, ?,?)";
getJdbcTemplate().update(sql,
new Object[] emp.getEmpId(), emp.getHealthInsuranceSchemeName(), emp.getCoverageAmount() );
@Override
public void deleteEmployeeHealthInsuranceById(String empid)
String sql = "DELETE FROM employeeHealthInsurance WHERE empId = ?";
getJdbcTemplate().update(sql, new Object[] empid );
11、创建用于执行员工操作的EmployeeService接口,如下所示:
package com.javainuse.service;
import com.javainuse.model.Employee;
public interface EmployeeService
void insertEmployee(Employee emp);
void deleteEmployeeById(String empid);
12、创建实现EmployeeService的EmployeeServiceImpl,如下所示:
package com.javainuse.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.javainuse.dao.EmployeeDao;
import com.javainuse.model.Employee;
import com.javainuse.service.EmployeeService;
@Service
public class EmployeeServiceImpl implements EmployeeService
@Autowired
EmployeeDao employeeDao;
@Override
public void insertEmployee(Employee employee)
employeeDao.insertEmployee(employee);
@Override
public void deleteEmployeeById(String empid)
employeeDao.deleteEmployeeById(empid);
13、创建HealthInsuranceService接口,如下所示:
package com.javainuse.service;
import com.javainuse.model.EmployeeHealthInsurance;
public interface HealthInsuranceService
void registerEmployeeHealthInsurance(EmployeeHealthInsurance employeeHealthInsurance);
void deleteEmployeeHealthInsuranceById(String empid);
14、创建HealthInsuranceServiceImpl,以实现HealthInsuranceService,如下所示:
package com.javainuse.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.javainuse.dao.HealthInsuranceDao;
import com.javainuse.model.EmployeeHealthInsurance;
import com.javainuse.service.HealthInsuranceService;
@Service
public class HealthInsuranceServiceImpl implements HealthInsuranceService
@Autowired
HealthInsuranceDao healthInsuranceDao;
@Override
public void registerEmployeeHealthInsurance(EmployeeHealthInsurance employeeHealthInsurance)
healthInsuranceDao.registerEmployeeHealthInsurance(employeeHealthInsurance);
@Override
public void deleteEmployeeHealthInsuranceById(String empid)
healthInsuranceDao.deleteEmployeeHealthInsuranceById(empid);
15、创建OrganisationService接口,如下所示:
package com.javainuse.service;
import com.javainuse.model.Employee;
import com.javainuse.model.EmployeeHealthInsurance;
public interface OrganizationService
public void joinOrganization(Employee employee, EmployeeHealthInsurance employeeHealthInsurance);
public void leaveOrganization(Employee employee, EmployeeHealthInsurance employeeHealthInsurance);
16、创建实现OrganizationService的OrganizationServiceImpl。它利用了EmployeeService和HealthInsuranceService。
package com.javainuse.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.javainuse.model.Employee;
import com.javainuse.model.EmployeeHealthInsurance;
import com.javainuse.service.EmployeeService;
import com.javainuse.service.HealthInsuranceService;
import com.javainuse.service.OrganizationService;
@Service
public class OrganzationServiceImpl implements OrganizationService
@Autowired
EmployeeService employeeService;
@Autowired
HealthInsuranceService healthInsuranceService;
@Override
public void joinOrganization(Employee employee, EmployeeHealthInsurance employeeHealthInsurance)
employeeService.insertEmployee(employee);
healthInsuranceService.registerEmployeeHealthInsurance(employeeHealthInsurance);
@Override
public void leaveOrganization(Employee employee, EmployeeHealthInsurance employeeHealthInsurance)
employeeService.deleteEmployeeById(employee.getEmpId());
healthInsuranceService.deleteEmployeeHealthInsuranceById(employeeHealthInsurance.getEmpId());
17、最后,如下创建Spring Boot Main类:
package com.javainuse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import com.javainuse.model.Employee;
import com.javainuse.model.EmployeeHealthInsurance;
import com.javainuse.service.OrganizationService;
@SpringBootApplication
public class SpringBootJdbcApplication
public static void main(String[] args)
ApplicationContext context = SpringApplication.run(SpringBootJdbcApplication.class, args);
OrganizationService organizationService = context.getBean(OrganizationService.class);
Employee emp = new Employee();
emp.setEmpId("emp1");
emp.setEmpName("emp1");
EmployeeHealthInsurance employeeHealthInsurance = new EmployeeHealthInsurance();
employeeHealthInsurance.setEmpId("emp1");
employeeHealthInsurance.setHealthInsuranceSchemeName("premium");
employeeHealthInsurance.setCoverageAmount以上是关于Spring Boot声明式事务管理示例的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot 揭秘与实战 数据存储篇 - 声明式事务管理