Spring Boot事务管理-事务回滚示例

Posted 独孤文彬

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Boot事务管理-事务回滚示例相关的知识,希望对你有一定的参考价值。

在先前的教程中,我们已经实现了 Spring Boot事务管理示例 -我们看到了什么是事务并实现了声明式事务管理。在以前的教程 -Spring Boot事务-了解事务传播中, 我们还研究了什么是传播以及使用Spring Boot的不同类型。在下一个教程中,我们将研究 什么是使用Spring Boot的事务隔离。 在Spring Boot事务管理示例中, 我们已经看到应用程序事务是一系列应用程序操作,这些操作被应用程序视为单个逻辑单元。

对于应用程序事务,如果任何操作失败,则所有其他操作都会回滚。在先前的事务管理示例中,我们通过引发未经检查的异常来测试了回滚。

但是,在实时方案中,将抛出已检查的异常。这些是基于某种逻辑的业务异常。
那么,如果发生“检查异常”,我们的交易将如何表现?在发生检查异常的情况下,即使我们使用了事务注释,先前执行的事务也不会自动回滚。 我们需要通知应用程序如何在发生检查异常时处理回滚。这可以通过RollbackFor注释实现。

视频讲解地址:(预留:待上传……)
让我们开始吧:
我们将修改我们 先前为事务管理创建的代码。
我们将创建一个称为InvalidInsuranceAmountException的自定义检查异常。根据我们的业务逻辑,如果保险额度小于零,则应抛出此异常。

创建自定义异常 如下-

package com.javainuse.service.impl;

public class InvalidInsuranceAmountException extends Exception 

	private static final long serialVersionUID = 1L;

	public InvalidInsuranceAmountException(String cause) 
		super(cause);
	

	

HealthInsuranceService接口为registerEmployeeHealthInsurance方法引发此异常。

package com.javainuse.service;

import com.javainuse.model.EmployeeHealthInsurance;
import com.javainuse.service.impl.InvalidInsuranceAmountException;

public interface HealthInsuranceService 
void registerEmployeeHealthInsurance(EmployeeHealthInsurance employeeHealthInsurance)
throws InvalidInsuranceAmountException;

	void deleteEmployeeHealthInsuranceById(String empid);

在registerEmployeeHealthInsurance的HealthInsuranceServiceImpl类中,我们进行了一项检查,以验证保险金额是否小于零。如果是,则抛出InvalidInsuranceAmountException。

package com.javainuse.service.impl;

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

import com.javainuse.dao.HealthInsuranceDao;
import com.javainuse.model.EmployeeHealthInsurance;
import com.javainuse.service.HealthInsuranceService;

@Service
@Transactional
public class HealthInsuranceServiceImpl implements HealthInsuranceService 

	@Autowired
	HealthInsuranceDao healthInsuranceDao;

	@Override
	public void registerEmployeeHealthInsurance(EmployeeHealthInsurance employeeHealthInsurance)
	throws InvalidInsuranceAmountException 
		
	if (employeeHealthInsurance.getCoverageAmount() < 0) 
		throw new InvalidInsuranceAmountException("Coverage Amount Should not be negative");
		
	healthInsuranceDao.registerEmployeeHealthInsurance(employeeHealthInsurance);
	

	@Override
	public void deleteEmployeeHealthInsuranceById(String empid) 
		healthInsuranceDao.deleteEmployeeHealthInsuranceById(empid);
	


joinOrganization方法的OrganizationService接口将引发InvalidInsuranceAmountException。

package com.javainuse.service;

import com.javainuse.model.Employee;
import com.javainuse.model.EmployeeHealthInsurance;
import com.javainuse.service.impl.InvalidInsuranceAmountException;

public interface OrganizationService 

	public void joinOrganization(Employee employee, EmployeeHealthInsurance employeeHealthInsurance)
	 throws InvalidInsuranceAmountException;

	public void leaveOrganization(Employee employee, EmployeeHealthInsurance employeeHealthInsurance);

在对HealthInsuranceService类进行调用的OrganzationServiceImpl中,我们将InvalidInsuranceAmountException记录到日志中并再次抛出。这是因为我们希望调用客户端知道发生了什么异常。

package com.javainuse.service.impl;

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

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
@Transactional
public class OrganzationServiceImpl implements OrganizationService 

	@Autowired
	EmployeeService employeeService;

	@Autowired
	HealthInsuranceService healthInsuranceService;

	@Override
	@Transactional
	public void joinOrganization(Employee employee, EmployeeHealthInsurance employeeHealthInsurance)
	throws InvalidInsuranceAmountException 
	employeeService.insertEmployee(employee);
	try 
		healthInsuranceService.registerEmployeeHealthInsurance(employeeHealthInsurance);
		 catch (InvalidInsuranceAmountException e) 
		throw new InvalidInsuranceAmountException("Exception is thrown");
		
	

	@Override
	public void leaveOrganization(Employee employee, EmployeeHealthInsurance employeeHealthInsurance) 
		employeeService.deleteEmployeeById(employee.getEmpId());
		healthInsuranceService.deleteEmployeeHealthInsuranceById(employeeHealthInsurance.getEmpId());
	

最后,在SpringBootJdbcApplication中,我们抛出InvalidInsuranceAmountException。

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.EmployeeService;
import com.javainuse.service.OrganizationService;
import com.javainuse.service.impl.InvalidInsuranceAmountException;

@SpringBootApplication
public class SpringBootJdbcApplication 
	
	
	@Autowired
	EmployeeService employeeService;

	public static void main(String[] args) throws InvalidInsuranceAmountException 
		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(0);
	
		organizationService.joinOrganization(emp, employeeHealthInsurance);
	

如果现在运行该应用程序-我们看到由于employeeHealthService中的异常而没有回退employeeService事务。

在数据库中,我们看到雇员表的插入尚未回滚,

但是事实并非如此。为了实现针对检查异常的回滚,我们需要使用Rollbackfor Annotation指定它。

package com.javainuse.service.impl;

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

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
@Transactional
public class OrganzationServiceImpl implements OrganizationService 

@Autowired
EmployeeService employeeService;

@Autowired
HealthInsuranceService healthInsuranceService;

@Override
@Transactional(rollbackFor = InvalidInsuranceAmountException.class)
public void joinOrganization(Employee employee, EmployeeHealthInsurance employeeHealthInsurance)
throws InvalidInsuranceAmountException 
	employeeService.insertEmployee(employee);
	try 
	healthInsuranceService.registerEmployeeHealthInsurance(employeeHealthInsurance);
	 catch (InvalidInsuranceAmountException e) 
	throw new InvalidInsuranceAmountException("Exception is thrown");
	


@Override
public void leaveOrganization(Employee employee, EmployeeHealthInsurance employeeHealthInsurance) 
	employeeService.deleteEmployeeById(employee.getEmpId());
	healthInsuranceService.deleteEmployeeHealthInsuranceById(employeeHealthInsurance.getEmpId());
	

现在再次运行该应用程序。我们看到由于employeeHealthService中的异常而回退了employeeService事务。

在数据库中,我们看到员工表的插入已回滚-

以上是关于Spring Boot事务管理-事务回滚示例的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 事务配置

Spring Boot事务配置管理

Spring boot,测试后事务不回滚

Spring Boot2 系列教程 | 实现声明式事务

Spring Boot 事物回滚

Spring Boot 事物回滚