1.方法内的自调用:spring事物是基于aop的,只要使用代理对象调用某个方法时,spring事物才能生效,而在一个方法内使用this.xxx()时。this并不是代理对象,所以会失效(实际上是@transaction注解失效)
解决办法:1.自己注入自己
2.把调用方法拆分到另一个bean中
3.AopContext.currentProxy()+@EnableAspectJAutoProxy(exposeProxy=true)
2.方法是private的 Spring事物是基于CGLIB进行aop,而CGLIB会基于父子类,子类是代理类,父类是被代理类,如果父类中的某个方法是private的。那么子类就没有办法重写它,也就没有办法额外增加Spring事物的逻辑
3。方法是final 的,原因和private一样,子类不能重写父类的fianl的方法
4.单独的线程方法调用:当mybatis或者jdbcTemplate执行sql时,会从ThreadLocal中获取数据库连接对象,如果开启事物的线程和执行sql的线程是同一个,那么就能拿到数据库连接对象,如果不是同一个线程,那么就拿不到,这样mybatis或者jdbcTemplate就会新建一个数据库连接执行sql
此时数据库的自动提交为true,那么sql执行完就会提交,后续有异常也不能回滚已经执行的额sql
5.没加@Configruration 注解,如果是springboot,没这个问题,如果是之前的spring,可能会有这个问题,这是因为mybatis或者jdbcTemplate执行sql时,会从ThreadLocal中获取数据库链接,但是threadlocal中存储的是map,map的key是datasource对象,value是连接对象,如果我们每日天假注解的话,会导致map中存储的datasource对象和mybatis和jdbctemplate对象不想等,从而拿不到数据库连接,导致自己去创建连接
6,异常被吃掉,如果spring没有捕获到一场,那么就不会回滚了,spring默认会补货runtimeException和Error
7.类没有被spring管理
8,数据库不支持事务