Spring事务的本质是数据库对事务的支持,数据库不支持事务,则Spring无法提供事务功能。
实现方式
- 编程式事务管理:使用TransactionTemplate 模板类处理;
- 声明式事务管理:建立在AOP基础上,对方法前后进行拦截,将事务处理的功能编织到拦截的方法中。@Transactional注解或xml文件中配置。只能作用到类,方法级别,无法作用到代码块级别。
事务的特性(ACID)
- 原子性(Atomicity):一个事务中的所有操作,或者全部完成,或者全部不完成。
- 一致性(Consistency):在事务开始之前和事务结束后,数据库的完整性没有被破坏;
- 隔离性(Isolation):数据库允许多个并发事务同时对其数据进行读写和修改的能力。隔离性可防止多个事务并发执行时由于交叉执行而导致数据的不一致。
- 持久化(Durability):事务处理结束后,对数据的修改就是永久的。
事务传播行为(Propagation)
当多个事务同时存在时,Spring 是如何处理这些事务的行为。
- PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务中;否则,就创建一个新事务;
- PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;否则,就以非事务执行;
- PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;否则,就抛出异常;
- PROPAGATION_REQUIRES_NEW:创建新事务。无论当前是否存在事务,都创建新事物执行;
- PROPAGATION_NOT_SUPPORTED:以非事务方式执行。如果当前存在事务,就把当前事务挂起。
- PROPAGATION_NEVER:以非事务方式执行。如果当前存在事务,则抛出异常;
- PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行。否则,按照REQUIRED 方式执行。
事务隔离级别(Isolation)
- ISOLATION_DEFAULT:默认隔离级别,使用数据库默认的事务隔离级别;Mysql默认采用的是REPEATABLE_READ,Oracle默认采用的是 READ_COMMITTED 。
- ISOLATION_READ_UNCOMMITTED:读未提交。最低的隔离级别。允许另外一个事务可以看到这个事务未提交的数据。可能会导致脏读、幻读和不可重复读。
- ISOLATION_READ_COMMITTED:读已提交。保证一个事务修改的数据,在提交后才能被另外一个事务读取。而且能看到该事务对已有记录的更新。可以阻止脏读,但是幻读或不可重复读仍可能发生。
- ISOLATION_REPEATABLE_READ:可重复读。对同一数据的多次读取结果都是一致的,除非数据是被本身事务自己所修改。可以阻止脏读和不可重复读,但幻读仍可能发生。(行锁仅仅加在了符合条件的记录行上)
- ISOLATION_SERIALIZABLE:最高的隔离级别。一个事务在执行的过程中,完全看不到其他事务对数据库所做的更新。可以防止脏读、不可重复读和幻读。
脏读、不可重复读和幻读
- 脏读:指当一个事务正在访问数据,并且对数据进行了修改,而修改数据还未提交到数据库中(可能提交或回滚)。此时,另外一个事务也在访问这个数据,然后使用了该数据。
- 不可重复读:一个事务先后读取同一条记录,而事务在两次读取之间,该数据被其他事务所修改,则两次读取的数据不同,称之为不可重复读。
- 幻读:指事务不是独立执行时发生的一种幻想。例如,第一个事务对一个表中的数据进行了更新update。同时第二个事务也修改了该表中数据,这种修改是向表中插入insert一行新数据。第一个事务的用户就会发现表中还存在没有修改的数据行,就好像发生了幻觉一样。一般解决幻读的方法是增加范围锁RangeS,锁定检索范围为只读,这样就避免了幻读。
运用到的设计模式
- 工厂设计模式:通过BeanFactory,ApplicationContext 创建bean对象;
- 代理设计模式:Spring AOP 功能的实现;
- 单例设计模式:Spring 中Bean 默认都是单例的;
- 模板方法模式:Spring 中 jdbcTemplate, redisTemplate等以Template 结尾的操作类;
- 适配器模式:Spring AOP 的增强或通知(Advice) 使用了适配器;Spring MVC 也用到了适配器模式。
- 观察者模式:Spring 事件驱动模型。