在先前的教程中,我们已经实现了 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事务。
在数据库中,我们看到员工表的插入已回滚-