Spring的事务

Spring的事务分为,声明式事务管理、编程式事务管理两种类型.由三大接口组成:PlatformTransactionManager(事务管理器)、TransactionDefinition(事务定义)、TransactionStatus(事务状态)。不同的事务管理器会对其进行不同的实现。

声明式事务管理

声明式的事务是无侵入式的,基于AOP,本质来说是对于一个方法执行前创建事务,方法执行后提交或者回滚。由于是基于方法级别的,所以声明式事务无法进行更好的细粒度,比如代码块的事务管理,不过我们可以提取代码块为一个方法来进行声明式事务,以做到更小粒度的事务管理。

Spring声明式事务的使用方式

Spring中声明式事务是由@Transactional来标注当前类和方法使用事务的方式,设置注解的不同属性后,Spring在调用这方法前会使用AOP在方法执行前根据声明的事务属性来创建对应的事务。

Transactional的源码
package org.springframework.transaction.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
/**
 * 描述单个方法或类上的事务属性。
 * 在类级别,此注释默认情况下适用于声明类及其子类的所有方法。
 * 注意,它不适用于类层次结构中的祖先类。
 * 需要在本地重新声明方法,以参与子类级别的注释
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
    /**
    * 指定要使用的事务管理器
    */
    @AliasFor("transactionManager")
    String value() default "";
   /**
    * 指定要使用的事务管理器
    */
    @AliasFor("value")
    String transactionManager() default "";

    String[] label() default {};
   /**
    * 事务传播机制,传播范围
    */
    Propagation propagation() default Propagation.REQUIRED;
   /**
    * 事务的隔离级别
    */
    Isolation isolation() default Isolation.DEFAULT;
   /**
    * 此事务的超时时间(以秒为单位)
    */
    int timeout() default -1;
   /**
    * 此事务的超时时间(以秒为单位)
    */
    String timeoutString() default "";
    /**
    * 事务是否是只读的
    */
    boolean readOnly() default false;
    /**
    * 指定异常一个或者多个,必须Throwable的子类,指示哪些异常类型必须引起事务回滚。
    */
    Class<? extends Throwable>[] rollbackFor() default {};

    String[] rollbackForClassName() default {};
   /**
    * 指定异常一个或者多个,必须Throwable的子类,指示哪些异常类型不需要引起事务回滚。
    */
    Class<? extends Throwable>[] noRollbackFor() default {};

    String[] noRollbackForClassName() default {};
}

声明式事务的五个特性

1.事务传播机制
  1. PROPAGATION_REQUIRED: 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
  2. PROPAGATION_SUPPORTS: 支持当前事务,如果当前没有事务,就以非事务方式执行。
  3. PROPAGATION_MANDATORY: 使用当前的事务,如果当前没有事务,就抛出异常。
  4. PROPAGATION_REQUIRES_NEW: 新建事务,如果当前存在事务,把当前事务挂起。
  5. PROPAGATION_NOT_SUPPORTED: 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
  6. PROPAGATION_NEVER: 以非事务方式执行,如果当前存在事务,则抛出异常。
  7. PROPAGATION_NESTED: 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
2.事务隔离机制
1. DEFAULT (默认)

这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与JDBC的隔离级别相对应。

2. READ_UNCOMMITTED (读未提交)

这是事务最低的隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。

3. READ_COMMITTED (读已提交)

保证一个事务修改的数据提交后才能被另外一个事务读取,另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。

4 .REPEATABLE_READ (可重复读)

这种事务隔离级别可以防止脏读、不可重复读,但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了不可重复读。

5. SERIALIZABLE(串行化)

这是花费最高代价但是最可靠的事务隔离级别,事务被处理为顺序执行。除了防止脏读、不可重复读外,还避免了幻像读。

3.只读

只读是当一个方法多次查询数据库,因为其它事务修改了数据导致不可重复读时,需要设置的属性。

只读如果为true,那么方法中不应该出现增删改。

4.事务超时

设置事务的超时时间

5.回滚规则

Spring是根据异常回滚的,可以指定多个异常来拦截回滚,如果生吞了异常就不会发生回滚。