既然讲到事务,那得明白什么是事务。事务就是一组独立不可分割的工作单元,事务中的操作要么全部执行,要么都不执行。一般来说,事务是必须满足4个条件(ACID)::原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。
-
原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
-
一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
-
隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
-
持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
知道了什么是事务和事务的四大特性,还要了解一下事务四种隔离级别,由低到高分别是「读未提交」、「读已提交」、「可重复读」和「可串行化」。
Spring 的事务其实分为两类:声明式事务管理和编程式事务管理。
了解完以上知识点,下面列举一些事务失效的原因,进入正题:
1、发生自调用。比如类中使用this调用本类的方法(这个this对象因为不是代理类,而是XXXService对象本事,所以会导致事务失效),解决办法就是让this变成XXXService的代理类即可。
2、方法不是public的。如果使用@Transaction注解开启事务的话,只能用于public方法上,如果不是public方法的话,只能开启Aspect代理模式。
3、数据库不支持事务。如果用MySQL,MySQL分几种引擎(InnoDB,MyISAM,Memory等),这里只有InnoDB支持事务。
4、没有被Spring容器管理。如果没有使用注解将类放进Spring容器中,即使加了@Transaction注解事务也是不会生效的。
5、异常没有抛出。如果异常没有抛出,事务还是不会生效的,如应该抛出
throw new RuntimeException();或者
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
我自己平时用的就是将
@Transactional(rollbackFor = Exception.class)放在public方法上 try{ //这里写你的业务,巴拉巴拉啦巴拉巴拉啦巴拉巴拉啦巴拉巴拉啦 } catch(Exception e) { log.error("巴拉巴拉啦", e); TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); }
注意:以上也是小白的我通过网上学习别人总结的东西进行记录,不保证正确性,如有雷同纯属巧合嘻嘻。