一、Spring管理事务的方式:

1.编程式事务(通过代码的方式来实现事务):编程式事务管理是侵入性事务管理,使用TransactionTemplate或者直接使用PlatformTransactionManager,对于编程式事务管理,Spring推荐使用TransactionTemplate。
2.声明式事务(通过配置的方式来实现事务):声明式事务管理建立在AOP之上,其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,执行完目标方法之后根据执行的情况提交或者回滚。

编程式事务每次实现都要单独实现,但业务量大功能复杂时,使用编程式事务无疑是痛苦的,而声明式事务不同,声明式事务属于无侵入式,不会影响业务逻辑的实现,只需要在配置文件中做相关的事务规则声明或者通过注解的方式,便可以将事务规则应用到业务逻辑中。

显然声明式事务管理要优于编程式事务管理,这正是Spring倡导的非侵入式的编程方式。唯一不足的地方就是声明式事务管理的粒度是方法级别,而编程式事务管理是可以到代码块的,但是可以通过提取方法的方式完成声明式事务管理的配置。

二、Spring中事务的隔离级别

隔离级别

含义

DEFAULT

使用后端数据库默认的隔离级别,Mysql 默认采用的 REPEATABLE_READ隔离级别 Oracle 默认采用的 READ_COMMITTED隔离级别.

READ_UNCOMMITTED

最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读

READ_COMMITTED

允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生

REPEATABLE_READ

对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。

SERIALIZABLE

最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别

三、Spring中事务的传播行为

事务的传播行为

含义

REQUIRED

如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般的选择(默认值)

SUPPORTS

支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)

MANDATORY

使用当前的事务,如果当前没有事务,就抛出异常

REQUERS_NEW

创建一个新的事务,如果当前存在事务,则把当前事务挂起。

NOT_SUPPORTED

以非事务方式运行,如果当前存在事务,则把当前事务挂起。

NEVER

以非事务方式运行,如果当前存在事务,抛出异常

NESTED

如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行REQUIRED类似的操作。

四、其他

@Transactional注解的使用
使用步骤:
1.配置事务管理器的bean


2.在业务层使用@Transactional注解 3.配置属性

  • isolation:配置事务的隔离级别,默认值是DEFAULT
  • proragation:用于指定事务的传播行为,默认是REQUIRED,表示一定有事务,增删改一般使用它,查询的话可以使用SUPPORTS
  • read-only:表示指定事务是否只读。默认为false(读写的时候用),查询用true
  • time-out:用于指定事务的超时时间,单位为秒,默认-1表示永不过期
  • rollback-for:用于指定一个异常,当产生该异常时事务回滚,其他异常不回滚。
  • no-rollback-for:用于指定一个异常,当产生该异常时事务不回滚,其他异常回滚。

@Transactional
作用于

  • 作用于接口:表明接口所有的实现类都有事务支持
  • 作用于类:表明该类的所有方法都有事务支持
  • 作用于方法:表明该方法有事务的支持

优先级:接口<类<方法

@Transactional有两点需要注意

只能声明在public的method。原因是spring是通过JDK代理或者CGLIB代理的,生成的代理类,只能处理public方法;
不能被类内部方法调用。还是因为代理的原因,类内部自调用,不会经过代理类,所以@Transactional不会生效

class A {
@Transactional
public void method1() {
method2();
}
@Transactional
public void method2() {
}
}

method1调用method2,不会触发method2的@Transactional声明。

在常见的ssm系统里,@Transactional会定义在controller的public方法上,因为一次请求往往意味着一连串的数据库操作,使用事务正好,一旦这次请求成功,则全部commit,一旦失败,则全部rooback。

还要继续深入 @Transactional,简单使用 @Transactional,只是使用默认的参数,不能完全满足业务需求。它含有的参数,是用来设置事务隔离级别和传播特性。

另外:以上参数大多比较好理解。关注点就在于事务的传播特性,当一个拥有事务的方法调用另外一个事务的方法,要理解好传播特性,才不会导致错误的事务处理。比如使用PROPAGATION_REQUIRES_NEW,事务和事务之间是隔离开的,内层事务失败不会影响外层事务。