Spring事务机制

来源:互联网 发布:不使用第三个变量 php 编辑:程序博客网 时间:2024/06/06 00:56

Spring事务管理涉及的接口的联系如下:

这里写图片描述

一、两种事务管理方式

1)声明式事务
声明式事务管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

2)编程式事务
编程式事务管理使用TransactionTemplate,或者直接使用底层的PlatformTransactionManager,Srping推荐使用TransactionTemplate。

二、Spring事务特性

Spring所有特性都在TransactionDefinition接口种定义:

  1. 隔离级别
    1)ISOLATION_DEFAULT
    表示底层数据库的默认隔离级别。
    对大部分数据库而言,默认值是ISOLATION_READ_COMMITTED。

    2)ISOLATION_READ_UNCOMMITTED
    该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读,不可重复读和幻读,因此很少使用该隔离级别。比如PostgreSQL实际上并没有此级别。

    3)ISOLATION_READ_COMMITTED
    该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。

    4)ISOLATION_REPEATABLE_READ
    该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。该级别可以防止脏读和不可重复读

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

    注意:
    不可重复读和幻读都是针对前后两次读的结果不一样,
    不可重复读针对修改的数据,
    幻读针对增加和删除的数据。

  2. 传播行为
    如果在开始当前事务之前,一个事务已经存在,指定一个事务的执行行为。

    1)PROPAGATION_REQUIRED(默认值)
    如果当前存在事务,则加入该事务;
    如果当前没有事务,则创建一个新的事务。

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

    3)PROPAGATION_SUPPORTS
    如果当前存在事务,则加入该事务;
    如果当前没有事务,则以非事务的方式继续运行。

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

    5)PROPAGATION_NEVER
    以非事务方式运行,如果当前存在事务,则抛出异常。

    6)PROPAGATION_MANDATORY
    如果当前存在事务,则加入该事务;
    如果当前没有事务,则抛出异常。

    7)PROPAGATION_NESTED
    如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;
    如果当前没有事务,则该取值等价PROPAGATION_REQUIRED。

  3. 只读
    只读事务用于客户端只读但不修改数据的情形,只读事务用于特定情景下的优化,比如使用Hibernate的时候。

  4. 超时
    所谓事务超时,就是指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。

  5. 回滚规则
    定义了哪些异常会导致事务回滚,哪些不会。
    默认情况下,事务只有遇到运行期异常时才会回滚,而在遇到检查型异常时不会回滚。
    可以运用规则,声明事务在遇到特定的检查型异常时回滚,也可以声明事务遇到特定的异常不回滚,即使这些异常是运行期异常。

三、事务的状态

事务的状态定义在TransactionStatus接口中,可以调用调用PlatformTransactionManager接口的getTransaction()得到。

public interface TransactionStatus{    boolean isNewTransaction(); // 是否是新的事物    boolean hasSavepoint(); // 是否有恢复点    void setRollbackOnly();  // 设置为只回滚    boolean isRollbackOnly(); // 是否为只回滚    boolean isCompleted; // 是否已完成}