1. 事务的传播:
- REQUIRED :如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。默认值。
- REQUIRES_NEW :创建一个新的事务,如果当前存在事务,则把当前事务挂起。(打印日志常用,即使前面回滚,该事务也会执行,记录报错信息)
指定方法:通过使用 propagation 属性设置,例如:
@Transactional(propagation = Propagation.REQUIRED)
2.事务的隔离级别:
- DEFAULT :这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是: READ_COMMITTED 。
- READ_UNCOMMITTED :该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读和不可重复读,因此很少使用该隔离级别。
- READ_COMMITTED :该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。
- REPEATABLE_READ :该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。该级别可以防止脏读和不可重复读。
- SERIALIZABLE :所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
指定方法:通过使用 isolation 属性设置,例如:
@Transactional(isolation = Isolation.DEFAULT)
2.单层事务
单层事务比较简单,直接用默认事务即可,但是必须指定触发哪种异常的时候,进行回滚数据。
Service单层事务控制
@Transactional(rollbackFor = Exception.class) //默认事务:propagation = Propagation.REQUIRED
@Service
public class FirstTransactionServiceImpl extends ServiceImpl<FirstTransactionMapper, FirstTransactionDO>
implements IFirstTransactionService {
@Override
@Transactional(rollbackFor = Exception.class)
public void insert(FirstTransactionDO firstTransaction) {
save(firstTransaction);
}
@Override
@Transactional(readOnly = true)
public List<FirstTransactionDO> listFirstTransactions() {
return list();
}
}
3. 嵌套事务
事务多层嵌套的事务,就必须考虑事务的传递性。
3.1 两层嵌套事务
-
Service第一层事务控制
@Transactional(rollbackFor = Exception.class)
默认事务:propagation = Propagation.REQUIRED -
第二层包装层的事务控制:第二层事务最好自定propagation, 最好不能使用propagation = Propagation.REQUIRES_NEW,使用了该类型的事务方法,不支持被其他方法调用的时候达到事务统一。
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
实例:
a) 第一层事务:
@Service
public class FirstTransactionServiceImpl extends ServiceImpl<FirstTransactionMapper, FirstTransactionDO>
implements IFirstTransactionService {
@Override
@Transactional(rollbackFor = Exception.class)
public void insert(FirstTransactionDO firstTransaction) {
save(firstTransaction);
}
@Override
@Transactional(readOnly = true)
public List<FirstTransactionDO> listFirstTransactions() {
return list();
}
}
@Service
public class SecondTransactionServiceImpl extends ServiceImpl<SecondTransactionMapper, SecondTransactionDO>
implements ISecondTransactionService {
@Override
@Transactional(rollbackFor = Exception.class)
public void insert(SecondTransactionDO secondTransaction) {
save(secondTransaction);
}
@Override
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public void insertByException(SecondTransactionDO secondTransaction) throws ServiceException {
save(secondTransaction);
throw new ServiceException(ServiceExceptionEnum.NOT_SUPPORT_TYPE);
}
/**
* 功能描述:
* 〈 hibernate不支持NESTED类型的事务 〉
*
* @param secondTransaction
* @return : void
* @throws :
* @author : yls
* @date : 2022/3/8 10:34
*/
@Override
@Transactional(propagation = Propagation.NESTED, rollbackFor = Exception.class)
public void insertNestedByException(SecondTransactionDO secondTransaction) throws ServiceException {
save(secondTransaction);
throw new ServiceException(ServiceExceptionEnum.NOT_SUPPORT_TYPE);
}
@Override
@Transactional(readOnly = true)
public List<SecondTransactionDO> listSecondTransactions() {
return list();
}
}
b) 第二层事务
@Slf4j
@Service
public class TransactionFacadeImpl implements ITransactionFacade {
@Resource
private IFirstTransactionService firstTransactionService;
@Resource
private ISecondTransactionService secondTransactionService;
@Override
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public void insetFirstAndSecondException(FirstTransactionDO firstTransaction, SecondTransactionDO secondTransaction) throws ServiceException {
/*
* 涉及图片保存、redis其他操作,均先保存数据库记录,然后再做其他操作、
* 这样才能保证其他操作出现异常,数据库信息能够自动回滚
*/
firstTransactionService.insert(firstTransaction);
secondTransactionService.insertByException(secondTransaction);
/*
* 其他业务处理:一定要放到数据库操作之后
*/
}
}
3.2 三层嵌套事务
-
Service第一层事务控制
@Transactional(rollbackFor = Exception.class)
默认事务:propagation = Propagation.REQUIRED -
第二层包装层的事务控制:
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) -
第三层嵌套包装层事务控制:
@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)
实例:
a) 第一层事务:
@Service
public class FirstTransactionServiceImpl extends ServiceImpl<FirstTransactionMapper, FirstTransactionDO>
implements IFirstTransactionService {
@Override
@Transactional(rollbackFor = Exception.class)
public void insert(FirstTransactionDO firstTransaction) {
save(firstTransaction);
}
@Override
@Transactional(readOnly = true)
public List<FirstTransactionDO> listFirstTransactions() {
return list();
}
}
@Service
public class SecondTransactionServiceImpl extends ServiceImpl<SecondTransactionMapper, SecondTransactionDO>
implements ISecondTransactionService {
@Override
@Transactional(rollbackFor = Exception.class)
public void insert(SecondTransactionDO secondTransaction) {
save(secondTransaction);
}
@Override
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public void insertByException(SecondTransactionDO secondTransaction) throws ServiceException {
save(secondTransaction);
throw new ServiceException(ServiceExceptionEnum.NOT_SUPPORT_TYPE);
}
/**
* 功能描述:
* 〈 hibernate不支持NESTED类型的事务 〉
*
* @param secondTransaction
* @return : void
* @throws :
* @author : yls
* @date : 2022/3/8 10:34
*/
@Override
@Transactional(propagation = Propagation.NESTED, rollbackFor = Exception.class)
public void insertNestedByException(SecondTransactionDO secondTransaction) throws ServiceException {
save(secondTransaction);
throw new ServiceException(ServiceExceptionEnum.NOT_SUPPORT_TYPE);
}
@Override
@Transactional(readOnly = true)
public List<SecondTransactionDO> listSecondTransactions() {
return list();
}
}
b) 第二层事务
```java
@Slf4j
@Service
public class TransactionFacadeImpl implements ITransactionFacade {
@Resource
private IFirstTransactionService firstTransactionService;
@Resource
private ISecondTransactionService secondTransactionService;
@Override
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public void insetFirstAndSecondException(FirstTransactionDO firstTransaction, SecondTransactionDO secondTransaction) throws ServiceException {
/*
* 涉及图片保存、redis其他操作,均先保存数据库记录,然后再做其他操作、
* 这样才能保证其他操作出现异常,数据库信息能够自动回滚
*/
firstTransactionService.insert(firstTransaction);
secondTransactionService.insertByException(secondTransaction);
/*
* 其他业务处理:一定要放到数据库操作之后
*/
}
}
c) 第三层事务
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class SecondTransactionFacadeImpl implements ISecondTransactionFacade {
@Resource
private ITransactionFacade transactionFacade;
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public void insetFirstAndSecond(FirstTransactionDO firstTransaction, FirstTransactionDO firstTransaction02,
SecondTransactionDO secondTransaction, SecondTransactionDO secondTransaction02) {
log.info("进入正常嵌套事务。");
transactionFacade.insetFirstAndSecond(firstTransaction, secondTransaction);
transactionFacade.insetFirstAndSecond(firstTransaction02, secondTransaction02);
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public void insetFirstAndSecondException(FirstTransactionDO firstTransaction, FirstTransactionDO firstTransaction02,
SecondTransactionDO secondTransaction, SecondTransactionDO secondTransaction02) throws ServiceException {
log.info("进入回滚嵌套事务。");
transactionFacade.insetFirstAndSecond(firstTransaction, secondTransaction);
transactionFacade.insetFirstAndSecondException(firstTransaction02, secondTransaction02);
}
@Override
@Transactional(propagation = Propagation.NESTED, rollbackFor = Exception.class)
public void insetNestedException(FirstTransactionDO firstTransaction,
FirstTransactionDO firstTransaction02,
SecondTransactionDO secondTransaction,
SecondTransactionDO secondTransaction02) throws ServiceException {
log.info("进入回滚嵌套事务。");
transactionFacade.insetFirstAndSecond(firstTransaction, secondTransaction);
transactionFacade.insetNestedException(firstTransaction02, secondTransaction02);
}
}
总结
一般不建议三层包装层嵌套,最多使用两层包装层+一层service事务嵌套