Spring的事务管理

Spring的事务管理

一、数据库事务

1.1 数据库事务的四个特性(ACID)

  • 原子性(Atomic)
  • 一致性(一致性是最终目标)(consistency)
  • 隔离性(isolation)
  • 持久性(durability)

1.2 数据并发的问题

  • 脏读(A事务读取B事务尚未提交的更改数据)
  • 不可重复读(A事务读取了B事务已经提交的更改数据)
  • 幻象读(A事务读取了B事务提交的新增数据)
  • 第一类丢失更新(A事务撤销时,把已经提交的B事务的更新数据覆盖了)
  • 第二类丢失更新(A事务覆盖了B事务已经提交的数据,造成B事务所做的操作丢失)

1.3 数据库锁机制

数据库通过锁机制解决并发访问的问题。

按锁定的对象的不同:

  • 表锁定:对整张表进行锁定
  • 行锁定:对表中的特定行进行锁定

从并发事务锁定的关系上看

  • 共享锁定
  • 独占锁定

1.4 事务的隔离级别

数据库为用户提供了锁的DML操作方式,但直接使用锁管理是非常麻烦的,因此数据库为用户提供了自动锁机制。只要用户指定会话的事务隔离级别,数据库就会分析事务中的SQL语句,然后自动为事务操作的数据资源添加适合的锁。

  • read uncommited
  • read commited
  • repeatable read
  • serializable

隔离级别和并发性是对立的。

1.5 JDBC对事务的支持

  • 不是所有的数据库都支持事务
  • 支持事务的数据库并非支持所有的事务隔离级别

二、ThreadLocal

ThreadLocal为每个使用该变量的线程分配一个独立的变量副本。

2.1 与Thread同步机制的比较

对于多线程资源共享的问题,同步机制采用“以时间换空间”的方式,访问串行化,对象共享化;而ThreadLocal采用了“以空间换时间”的方式,访问并行化,对象独享化。

三、Spring对事务管理的支持

3.1 事务管理关键抽象

Spring事务管理SPI(Service Provider Interface)的抽象层主要包含3个接口:PlatformTransactionManagerTransactionDefinitionTransactionStatus

  • TransactionDefinition: 定义Spring兼容的事务属性,事务隔离事务传播超时时间只读状态

    只读事务不修改任何数据,资源事务管理者可以针对可读事务应用一些优化措施,提高运行性能。只读事务在某些情况下(如使用Hibernate时)是一种非常有用的优化,试图在只读事务中更改数据将引发异常。

  • TransactionStatus: 代表一个事务的具体运行状态

  • PlatformTransactionManager: 根据TransactionDefinition提供的事务属性配置信息创建事务,并用TransactionStatus描述这个激活事务的状态。

3.2 Spring的事务管理器实现类

Spring为不同的持久化框架提供了PlatformTransactionManager接口的实现类:

  • JpaTransactionManager
  • HibernateTransactionManager
  • DataSourceTransactionManager
  • JtaTransactionManager 具有多个数据源的全局事务使用该事务管理器(不管采用何种持久化技术)

四、Spring的事务传播

事务传播是Spring进行事务管理的重要概念。

Spring在TransactionDefinition中规定了7种类型的事务传播行为:

  • PROPAGATION_REQUIRED 如果当前没有事务,则新建一个事务;如果已经存在一个事务,则加入到这个事务中,这是最常见的选择。
  • PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,则以非事务方式执行;
  • PROPAGATION_MANDATORY 使用当前事务,如果当前没有事务,则抛出异常;
  • PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,则将当前事务挂起;
  • PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,则把当前事务挂起;
  • PROPAGATION_NEVER 以非事务方式执行。如果当前存在事务,则抛出异常;
  • PROPAGATION_NESTED如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

五、事务配置

5.1 使用原始的TransactionProxyFactoryBean

(1) 声明式事务配置

  • <prop>的配置规则: PROPAGATION(传播属性),ISOLATION(隔离级别),readOnly(是否为只读事务),-Exception(发生异常时回滚事务),+Exception(发生异常时照样提交事务)
  • 传播事务是唯一必须提供的配置项,当<prop>的值为空时,不会发生异常,但对应的配置方法不会应用事务,相当于没有配置
  • Spring默认的事务回滚规则为“运行期异常回滚,检查型异常不回滚”;
<!--    基于数据源的事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
          p:dataSource-ref="dataSource"/>

<!--    需要实施增强的目标业务-->
    <bean id="bbtForum"
          class="com.hef.service.BbtForum"
          p:forumDao-ref="forumDao"
          p:topicDao-ref="topicDao"
          p:postDao-ref="postDao"/>

<!--    使用事务代理工厂为目标业务Bean提供事务增强 -->
    <bean id="bbtForum" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="transactionManager" ref="transactionManager"/>
        <property name="target" >
            <ref bean="bbtForum"></ref>
        </property>
        <property name="transactionAttributes">
            <props>
                <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>

(2) 基于aop/tx命名空间的配置

<!--    基于数据源的事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
          p:dataSource-ref="dataSource"/>
    
<!--    使用强大的切点表达式语言轻松定义目标方法 -->
    <aop:config>
<!--        将 com.hef.service 包下所有以Forum为前缀的类所有方法纳入事务增强范围 -->
        <aop:pointcut id="serviceMethod" expression="execution(* com.hef.service.Forum*.*(..))"/>
<!--        引用事务增强-->
        <aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice"/>
    </aop:config>
    
<!--    事务增强-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
<!--            name、propagation、isolation、timeout、read-only、rollback-for、no-rollback-for -->
            <tx:method name="get*" read-only="false"/>
            <tx:method name="add*" rollback-for="Exception"/>
            <tx:method name="update*"/>
        </tx:attributes>
    </tx:advice>

(3) 基于注解的声明式事务

<!--    基于数据源的事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
          p:dataSource-ref="dataSource"/>
    
<!--    对标注@Transactional注解对Bean进行加工处理, 以织入事务管理切面-->
    <tx:annotation-driven transaction-manager="transactionManager"/>
  • 注解本身具有一组普适性的默认事务属性,所以往往只要在事务管理的业务类中添加一个@Transactional注解,就完成了业务类食物属性的配置;

  • @Transactional的属性,可以配置:传播行为,隔离级别,读写属性,超时时间,回滚设置

  • Spring建议在具体的业务类上使用@Transaction注解;

    注解不能被继承

  • 在方法出的注解回覆盖类定义处的注解

  • 可以同时使用不同的事务管理器

©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页