spring事务的回滚,方法中只要有truncate ,全都回滚失效。所以吖,要在事务结束后,根据事务的状态是否回滚,做truncate操作,因为mysql truncate 没有事务。代理里要写在trycatch 之后的finally 里面。
spring事务的使用,有三种方式。
1】.@Transactional注解
使用该注解,必需要在spring管理的bean 中使用,可使用在类/方法上。需要注意:方法包含try ..catch ,该注解失效。以及多线程下,该注解失效。一般用在dao层或者使用mybatis,就用在mapper调用的service层。
事务注解要在public 方法上才生效
springboot+mybatis 事务失效的原因:springboot 默认提供的事务是jpa,你用的是mybatis,要加bean DtataSourceTransactionManager.
2】.TransactionTemplate(使用此方法,注意别嵌套,容易出二次异常unexpectedrollbackexception)
多线程以及try catch 中可以使用该方式。但是要注意,transactionTemplate.execute();不要重复嵌套使用,容易抛异常。unexpectedrollbackexception;; 解决方式其中一种是使用try catch 。
如果只是单事务的情况下,第一层简单操作使用@transactional ,第二层业务逻辑使用TransactionTemplate,第三层使用TransactionTemplate,然后第二层套异常,直接catch,然后里面再使用status.setRollBackOnly(),这个异常不是sql异常,就会触发unexpectedrollbackexception异常。
解决方式:第三层添加trycatch ,第三层代码:
举个栗子:
int num=0;
try{
num=service.add();
}catch(Exception e)
{
...log
}
然后如果catch里面没有return ;或者continue;那么代码会继续执行下去。
事务的循环就需要这样的trycatch 机制,让事务循环起来。
记住事务的循环,回滚了要记得continue;还要干下一条呢。
ps 与事务无关的跳出foreach 循环的方式,使用break无效,要在foreach 或者list.for (for(int i :list))最外层添加try,catch .循环体中throw new RunTimeException() 跳出循环。
unexpectedrollbackexception 异常解决方式总结:
1.异常机制:第三层用try /catch
2.判断是否sql异常:第二层catch(Expection e){ if(e instanceof SQLException){} }
3.第二层可以去掉TransactionTemplate 也可以解决这个异常。
4.如果线程运行异常就结束,这个异常算二次异常,没有影响业务也可以不处理。
5.如果希望内层事务回滚,但不影响外层事务提交,需要将内层事务的传播方式指定为PROPAGATION_NESTED。注:PROPAGATION_NESTED基于数据库savepoint实现的嵌套事务,外层事务的提交和回滚能够控制嵌内层事务,而内层事务报错时,可以返回原始savepoint,外层事务可以继续提交。
3】.aop+transaction
两种方式:xml /java代码,使用这个最方便快捷。