spring事务上的坑
1.前言
近期有位同事看了我的定时器代码,提醒我一个隐藏bug——spring事务
在方法内调用事务,事务无法生效!于是我开始测试与整理spring事务中可能遇到的坑
2.问题复现
如下代码,在类内部调用事务是不会生效的,因为没有走类代理!事务是切在类上,只有通过调用 类.方法
才会走spring的事务管理!
@Component
public class TimerTest {
private static final Logger logger = LoggerFactory.getLogger(TimerTest.class);
@Autowired
private SysDaoAgent agent;
@Autowired
private ServiceTest serviceTest;
@Scheduled(fixedRate = 10 * 60 * 1000, initialDelay = 5 * 1000)
public void start() {
test();//不走代理
// serviceTest.test();//切面切在类上
((TimerTest)AopContext.currentProxy()).test();//获取当前代理再去调用才行
}
@Transactional
public void test(){
agent.quickSimpleDao.update("update qhb_star_user set is_del = 5 where seq_id=8299");
if(true){
throw new RuntimeException("err");
}
agent.quickSimpleDao.update("update qhb_star_user set is_del = 2 where seq_id=8298");
}
}
3.其他常见的事务坑
1、首先要看数据库本身对应的库、表所设置的引擎是什么。MyIsam不支持事务,如果需要,则必须改为InnnoDB。
2、@Transactional所注解的方法是否为public
3、@Transactional所注解的方法所在的类,是否已经被注解@Service或@Component等。
4、需要调用该方法,且需要支持事务特性的调用方是在在 @Transactional所在的类的外面。注意:类内部的其他方法调用这个注解了@Transactional的方法,事务是不会起作用的。
5、注解为事务范围的方法中,事务的回滚仅仅对于unchecked的异常有效。对于checked异常无效。也就是说事务回滚仅仅发生在出现RuntimeException或Error的时候。
如果希望一般的异常也能触发事务回滚,需要在注解了@Transactional的方法上,将@Transactional回滚参数设为:
@Transactional(rollbackFor=Exception.class)
6、非springboot项目,需要检查spring配置文件xml中:
(1)扫描包范围是否配置好,否则不会在启动时spring容器中创建和加载对应的bean对象。
<context:component-scan base-package="com.happybks" ></context:component-scan>
(2)事务是否已经配置成开启
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
4.总结
对于事务一定要重视,重视,再重视!为什么?作为程序员,这还需要解释么?
更多事务原理请具体查看 链接