在抛出异常的服务中使用@Transactional(propagation = Propagation.REQUIRES_NEW) 会影响其他与@Transactional 关联的服务
Using @Transactional(propagation = Propagation.REQUIRES_NEW) in a service throwing Exception affects other associated service with @Transactional
我有服务 1 的方法使用@Transactional 调用服务 2 和服务 3 的方法。
现在,
Scenario_1(工作场景):
Service-1:
@Transactional
void m1() {
m2(); // of Service 2
m3(); // of Service 3
}
Service-2:
@Transactional(propagation = Propagation.REQUIRES_NEW)
void m2() {
//1. Insert Employee
}
Service-3:
@Transactional
void m3() {
// 1. Insert Insurance
// 2. Throw RuntimeException
}
Result:
1. Employee inserted
2. Insurance object not inserted (i.e. rolled back)
Scenario_2(未获得预期结果):
(将“propagation = Propagation.REQUIRES_NEW”放在 Service-3 方法而不是 Service-2 方法中)
Service-2:
@Transactional
void m2() {
//1. Insert Employee
}
Service-3:
@Transactional(propagation = Propagation.REQUIRES_NEW)
void m3() {
// 1. Insert Insurance
// 2. Throw RuntimeException
}
Result:
1. Employee not inserted (why ?)
2. Insurance not inserted (i.e. rolled back)
在 Scenario_2 中,Service-3 中的异常是否应该影响(回滚)Service-2,因为 Service-3 在新事务中是 运行?我的理解是正确的还是我遗漏了什么?请提出建议。
以下为实际参考文件(工作场景):
1. OrganzationServiceImpl.java
@Service
public class OrganzationServiceImpl implements OrganizationService {
@Autowired
EmployeeService employeeService;
@Autowired
HealthInsuranceService healthInsuranceService;
@Transactional
@Override
public void joinOrganization(Employee employee, EmployeeHealthInsurance employeeHealthInsurance) {
employeeService.insertEmployee(employee);
healthInsuranceService.registerEmployeeHealthInsurance(employeeHealthInsurance);
}
}
2. EmployeeServiceImpl.java
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
EmployeeDao employeeDao;
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void insertEmployee(Employee employee) {
employeeDao.insertEmployee(employee);
}
}
3. HealthInsuranceServiceImpl.java
@Service
public class HealthInsuranceServiceImpl implements HealthInsuranceService {
@Autowired
HealthInsuranceDao healthInsuranceDao;
@Transactional
@Override
public void registerEmployeeHealthInsurance(EmployeeHealthInsurance employeeHealthInsurance) {
healthInsuranceDao.registerEmployeeHealthInsurance(employeeHealthInsurance);
if (employeeHealthInsurance.getEmpId().equals("emp1")) {
throw new RuntimeException("thowing RuntimeException for testing");
}
}
}
据我了解,问题是在场景 2 中,来自 Service-1 的事务也被回滚,因为您没有处理来自 Service-3 的 RuntimeException
。由于 Service-2 在这种情况下与 Service-2 在同一事务中,因此回滚了员工插入。
这在场景 1 中不会发生,因为您有一个单独的 Service-2 事务。
我有服务 1 的方法使用@Transactional 调用服务 2 和服务 3 的方法。
现在, Scenario_1(工作场景):
Service-1:
@Transactional
void m1() {
m2(); // of Service 2
m3(); // of Service 3
}
Service-2:
@Transactional(propagation = Propagation.REQUIRES_NEW)
void m2() {
//1. Insert Employee
}
Service-3:
@Transactional
void m3() {
// 1. Insert Insurance
// 2. Throw RuntimeException
}
Result:
1. Employee inserted
2. Insurance object not inserted (i.e. rolled back)
Scenario_2(未获得预期结果): (将“propagation = Propagation.REQUIRES_NEW”放在 Service-3 方法而不是 Service-2 方法中)
Service-2:
@Transactional
void m2() {
//1. Insert Employee
}
Service-3:
@Transactional(propagation = Propagation.REQUIRES_NEW)
void m3() {
// 1. Insert Insurance
// 2. Throw RuntimeException
}
Result:
1. Employee not inserted (why ?)
2. Insurance not inserted (i.e. rolled back)
在 Scenario_2 中,Service-3 中的异常是否应该影响(回滚)Service-2,因为 Service-3 在新事务中是 运行?我的理解是正确的还是我遗漏了什么?请提出建议。
以下为实际参考文件(工作场景):
1. OrganzationServiceImpl.java
@Service
public class OrganzationServiceImpl implements OrganizationService {
@Autowired
EmployeeService employeeService;
@Autowired
HealthInsuranceService healthInsuranceService;
@Transactional
@Override
public void joinOrganization(Employee employee, EmployeeHealthInsurance employeeHealthInsurance) {
employeeService.insertEmployee(employee);
healthInsuranceService.registerEmployeeHealthInsurance(employeeHealthInsurance);
}
}
2. EmployeeServiceImpl.java
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
EmployeeDao employeeDao;
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void insertEmployee(Employee employee) {
employeeDao.insertEmployee(employee);
}
}
3. HealthInsuranceServiceImpl.java
@Service
public class HealthInsuranceServiceImpl implements HealthInsuranceService {
@Autowired
HealthInsuranceDao healthInsuranceDao;
@Transactional
@Override
public void registerEmployeeHealthInsurance(EmployeeHealthInsurance employeeHealthInsurance) {
healthInsuranceDao.registerEmployeeHealthInsurance(employeeHealthInsurance);
if (employeeHealthInsurance.getEmpId().equals("emp1")) {
throw new RuntimeException("thowing RuntimeException for testing");
}
}
}
据我了解,问题是在场景 2 中,来自 Service-1 的事务也被回滚,因为您没有处理来自 Service-3 的 RuntimeException
。由于 Service-2 在这种情况下与 Service-2 在同一事务中,因此回滚了员工插入。
这在场景 1 中不会发生,因为您有一个单独的 Service-2 事务。