spring事务的应用

一、spring事务的概念

   1、spring事务

     事务在我们日常开发相关业务服务是最常见的情况,这里就介绍一下相关spring事务的应用,spring的事务大大方便了我们也如开发,首先spring的事务管理不需要与我们特定的事务api耦合,允许应用开发者在任何环境下使用一致的编程模型。其实是spring抽象出来一个叫做PlatformTransactionManager的接口,该接口提供了有关事务的开启,回滚,提交等操作,我们只需要和该接口打交道(使用spring 编程式事务,如果是使用声明式事务则我们可能也不需要了解该借口)。而具体的是属于jdbc的connection事务,还是Hibernate的session事务,亦或JTA相关的全局事务由spring帮我们屏蔽掉具体的实现细节(面向借口编程)。同时Spring同时支持编程式事务管理和声明式事务管理。

   2、spring事务的相关类

二、spring事务的属性

      1、隔离级别

隔离级别 含义
ISOLATION_DEFAULT 使用后端数据库默认的隔离级别。
ISOLATION_READ_UNCOMMITTED 允许读取尚未提交的更改。可能导致脏读、幻影读或不可重复读。
ISOLATION_READ_COMMITTED 允许从已经提交的并发事务读取。可防止脏读,但幻影读和不可重复读仍可能会发生。
ISOLATION_REPEATABLE_READ 对相同字段的多次读取的结果是一致的,除非数据被当前事务本身改变。可防止脏读和不可重复读,但幻影读仍可能发生。
ISOLATION_SERIALIZABLE 完全服从ACID的隔离级别,确保不发生脏读、不可重复读和幻影读。这在所有隔离级别中也是最慢的,因为它通常是通过完全锁定当前事务所涉及的数据表来完成的。

    有关事务隔离级别的相关https://blog.csdn.net/liushangzaibeijing/article/details/82888778

  2、传播行为

事务的第一个方面是传播行为。传播行为定义关于客户端和被调用方法的事务边界。Spring定义了7中传播行为。

传播行为 意义
PROPAGATION_MANDATORY 表示该方法必须运行在一个事务中。如果当前没有事务正在发生,将抛出一个异常
PROPAGATION_NESTED 表示如果当前正有一个事务在进行中,则该方法应当运行在一个嵌套式事务中。被嵌套的事务可以独立于封装事务进行提交或回滚。如果封装事务不存在,行为就像PROPAGATION_REQUIRES一样。
PROPAGATION_NEVER 表示当前的方法不应该在一个事务中运行。如果一个事务正在进行,则会抛出一个异常。
PROPAGATION_NOT_SUPPORTED 表示该方法不应该在一个事务中运行。如果一个现有事务正在进行中,它将在该方法的运行期间被挂起。
PROPAGATION_SUPPORTS 表示当前方法不需要事务性上下文,但是如果有一个事务已经在运行的话,它也可以在这个事务里运行。
PROPAGATION_REQUIRES_NEW 表示当前方法必须在它自己的事务里运行。一个新的事务将被启动,而且如果有一个现有事务在运行的话,则将在这个方法运行期间被挂起。
PROPAGATION_REQUIRES 表示当前方法必须在一个事务中运行。如果一个现有事务正在进行中,该方法将在那个事务中运行,否则就要开始一个新事务。

       3、超时时间

     所谓事务超时,就是指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。在 TransactionDefinition 中以 int 的值来表示超时时间,其单位是秒。默认设置为底层事务系统的超时值,如果底层数据库事务系统没有设置超时值,那么就是none,没有超时限制。

注意点:Spring事务超时时间 = 事务开始时到最后一个Statement创建时时间 + 最后一个Statement的执行时超时时间(即其queryTimeout)。所以在在执行Statement之外的超时无法进行事务回滚。

       4、只读状态

   所谓只读状态是指在该事务状态下(与具体的数据库实现有关),只能针对该数据库执行查找的操作,其他对数据库的修改则会抛出异常。

       5、异常回滚

 默认spring事务只在发生未被捕获的 runtimeexcetpion时才回滚。  
   spring aop  异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样aop代理才能捕获到方法的异常,才能进行回滚,默认情况下aop只捕获runtimeexception的异常,但可以通过  配置来捕获特定的异常并回滚 。

这里主要RollbackForClassName 碰到指定的异常类进行回滚,spring事务默认对 noRollbackForClassName 对于指定异常不进行回滚

Spring框架的事务基础架构代码将默认地 只 在抛出运行时和unchecked exceptions时才标识事务回滚。 也就是说,当抛出个RuntimeException 或其子类例的实例时。(Errors 也一样 - 默认地 - 标识事务回滚。)从事务方法中抛出的Checked exceptions将 不 被标识进行事务回滚。

1 让checked例外也回滚:在整个方法前加上 @Transactional(rollbackFor=Exception.class)

2 让unchecked例外不回滚: @Transactional(notRollbackFor=RunTimeException.class)

3 不需要事务管理的(只查询的)方法:@Transactional(propagation=Propagation.NOT_SUPPORTED)

注意: 如果异常被try{}catch{}了,事务就不回滚了,如果想让事务回滚必须再往外抛try{}catch{throw Exception}。

注意:

  • Spring团队的建议是你在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。你当然可以在接口上使用 @Transactional 注解,但是这将只能当你设置了基于接口的代理时它才生效。因为注解是不能继承的,这就意味着如果你正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装(将被确认为严重的)。因此,请接受Spring团队的建议并且在具体的类上使用 @Transactional 注解。
  • @Transactional 注解标识的方法,处理过程尽量的简单。尤其是带锁的事务方法,能不放在事务里面的最好不要放在事务里面。可以将常规的数据库查询操作放在事务前面进行,而事务内进行增、删、改、加锁查询等操作。

猜你喜欢

转载自blog.csdn.net/liushangzaibeijing/article/details/82925403