Spring声明式事务@Transactional知识点分享

2020-02-18 10:02:34丽君

@Transactional注解支持9个属性的设置,这里只讲解其中使用较多的三个属性:readOnly、propagation、isolation。其中propagation属性用来枚举事务的传播行为,isolation用来设置事务隔离级别,readOnly进行读写事务控制。

@Service
@Transactional(readOnly = true)
public class AppTradeRec2Service extends BaseService {
 @Autowired
 private AppTradeRecDao appTradeRecDao;
 @Autowired
 private ConsInfoDao consInfoDao;
 
 @Transactional(readOnly = false)
 public void payCharge(TradeRec tradeRec) {
 User usr = UserUtils.getUser();
 ConsInfo cons = consInfoDao.getByUser(usr.getId());
 //修改交易记录
 tradeRec.setPayBefore(cons.getAccountAmt());
 tradeRec.setPayAfter(cons.getAccountAmt() - tradeRec.getRcvAmt());
 tradeRec.setIsPay("99");
 appTradeRecDao.save(tradeRec);
 //修改账户余额
 cons.setAccountAmt(cons.getAccountAmt() - tradeRec.getRcvAmt());
 consInfoDao.save(cons);
 }
}

一、readOnly读写事务控制

readOnly=true表明所注解的方法或类只是读取数据。

readOnly=false表明所注解的方法或类是增加,删除,修改数据。

二、isolation事务隔离级别

我们在使用事务过程中,通常会发生以下三种情况:

1、脏读(dirty read):当一个事务读取另一个事务尚未提交的修改时,产生脏读。

2、不可重复读(non-repeatable read):同一查询在同一事务中多次进行,由于其他提交事务所做的修改或删除,每次返回不同的结果集,此时发生非重复读。

3、幻像读(phantom read):同一查询在同一事务中多次进行,由于其他提交事务所做的插入操作,每次返回不同的结果集,此时发生幻像读。

针对上述三种情况,Spring提供了5种事务隔离级别予以解决:

1、DEFAULT默认级别

DEFAULT为数据源(数据库)的默认隔离级别,以目前常用的MySQL为例,默认的隔离级别通常为REPEATABLE_READ。

2、READ_UNCOMMITTED未授权读取级别

这是最低的隔离级别,一个事务能读取到别的事务未提交的更新数据,很不安全,可能出现丢失更新、脏读、不可重复读、幻读。

3、READ_COMMITTED授权读取级别

以操作同一行数据为前提,读事务允许其他读事务和写事务,未提交的写事务禁止其他读事务和写事务。此隔离级别可以防止更新丢失、脏读,但不能防止不可重复读、幻读。此隔离级别可以通过“瞬间共享读锁”和“排他写锁”实现。

4、REPEATABLE_READ可重复读取级别

保证同一事务中先后执行的多次查询将返回同一结果,不受其他事务影响。以操作同一行数据为前提,读事务禁止其他写事务,但允许其他读事务,未提交的写事务禁止其他读事务和写事务。此隔离级别可以防止更新丢失、脏读、不可重复读,但不能防止幻读。