本文主要讲Spring的事务控制,主要分为两种1.编程式事务管理 2.声明式事务管理。
简单说一下 编程式事务管理就是用代码去管理事务,Spring推荐使用TransactionTemplate进行管理。声明式事务管理则是使用xml 或注解的方式进行管理。
xml方式
图片来自互联网
注解就是今天的主角@Transactional
当@Transactional使用在接口、类上时代表该接口、类的所有方法都被事务控制了。也可以直接用在接口、类的方法上面。不过@Transactional只对public方法起作用,使用在其它修饰符上时会被忽略,不会报错。还有就是只有外部调用方法才会启动事务,即类自己内部的方法调用是不会触发事务的。
--------------------------------------分割线-------------------------------------------------------------------------------------------------
关于使用@Transactional的方法在使用try..catch之后无法回滚的问题。这是由于@Transactional只有在抛出RuntimeException或者它的子类的时候才会回滚。解决方法有很多先说编程式的处理方法。
1.手动抛出一个RuntimeException异常即可。如:(代码来自互联网)
if(userSave){
try {
userDao.save(user);
userCapabilityQuotaDao.save(capabilityQuota);
} catch (Exception e) {
logger.info("能力开通接口,开户异常,异常信息:"+e);
throw new RuntimeException();
}
}
2.使用TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 进行手动回滚。
如:(代码来自互联网)
if(userSave){
try {
userDao.save(user);
userCapabilityQuotaDao.save(capabilityQuota);
} catch (Exception e) {
logger.info("能力开通接口,开户异常,异常信息:"+e);
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
这两种方法也很方便但代码侵入性太强个人不喜欢
第二就是声明式的方法。
思路就是让@Transactional遇到其它异常也正常回滚即可。那我们就可以请出异常的老祖宗了
1.在注解的属性上做文章使其遇到异常就回滚
@Transactional(rollbackForClassName={"Exception"})或者@Transactional(rollbackFor={Exception.class})
2.使用xml进行配置但思路是一样的
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true" rollback-for="Exception"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>