1. 数据库引擎选择错误
2.@transactional标注的方法 所在的类需要被spring管理 并且方法是public修饰
3. 自调用的时候出现的事务失效:
1 @Service 2 public class Service{ 3 4 public void m(){ 5 m1(); 6 m2(); 7 8 } 9 10 @transactional 11 public void m1(){ 12 13 14 } 15 @transactional 16 public void m2(){ 17 18 } 19 }
1 @Service 2 public class DmzService { 3 @Transactional 4 public void save(A a, B b) { 5 saveB(b); 6 } 7 8 @Transactional(propagation = Propagation.REQUIRES_NEW) 9 public void saveB(B b){ 10 dao.saveB(b); 11 } 12 }
以上两种情况皆会导致事务失败,原因是 自调用调用的是目标类而不是代理类的方法,所以解决问题的点也在这里
使用代理类的方法是
1. 自己autowire注入自己
2. 使用aopcontext
@Service public class DmzService { @Transactional public void save(A a, B b) { ((DmzService) AopContext.currentProxy()).saveB(b); } @Transactional(propagation = Propagation.REQUIRES_NEW) public void saveB(B b){ dao.saveB(b); } }
// exposeProxy=true代表将代理类放入到线程上下文中,默认是false
@EnableAspectJAutoProxy(exposeProxy = true)
事务回滚问题
1. 想回滚却提交了
spring默认回滚是发生了error或者RunTimeException 如果想要回滚其他的异常 需要制定rollbackfor
2. 想提交却回滚了
@Service public class DmzService { @Autowired IndexService indexService; @Transactional public void testRollbackOnly() { try { indexService.a(); } catch (ClassNotFoundException e) { System.out.println("catch"); } } } @Service public class IndexService { @Transactional(rollbackFor = Exception.class) public void a() throws ClassNotFoundException{ // ...... throw new ClassNotFoundException(); } }
以上代码会抛出异常! 原因是 事务嵌套的情况下,当内部事务回滚会把rollbackOnly属性设置为true 所以会回滚
解决:
1. 如果想内部事务回滚 外部事务继续执行
将内部事务的传播级别设置为nested或者requires_new
@Transactional(rollbackFor = Exception.class,propagation = Propagation.NESTED)
2. 想内部事务发生异常 外部事务回滚 整体回滚 不抛异常
@Transactional public void testRollbackOnly() { try { indexService.a(); } catch (ClassNotFoundException e) { // 加上这句代码 TransactionInterceptor.currentTransactionStatus().setRollbackOnly(); } }