文章目录

  • 1. Spring中的事务机制
  • 2. 声明式事务
  • 2.1 基于XML方式的声明式事务
  • 2.2 基于Annotation(注解)方式的声明式事务
  • 3. Spring事务的隔离级别isolation(5种)
  • 4. Spring事务的传播行为propagation(7种)


1. Spring中的事务机制

Spring中的事务分为两种方式:分别是编程式事务声明式事务

  • 编程式事务:通过编写代码实现的事务管理,包括定义事务的开始,正常执行后的事务提交和发生异常时的事务回滚。
  • 声明式事务:通过AOP技术实现的事务管理,其主要思想是将事务管理作为一个“切面”代码单独编写,然后通过AOP技术将事务管理的“切面”植入业务目标类中。

Spring声明式事务的本质是使用AOP对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。

声明式事务的最大优点在于开发者无须通过编程的方式来管理事务,使得我们不需要去处理获得连接、关闭连接、事务提交和回滚等这些操作。只需在配置文件中进行相关的事务规则声明,就可以将事务规则应用到业务逻辑中。所以,通常推荐使用声明式事务管理。

事务属性通常是指事务的传播行为,事务的隔离级别,事务的超时值和事务只读标志组成。

2. 声明式事务

Spring使用AOP来支持声明式事务,会根据事务属性,自动在方法调用之前决定是否开启一个事务,并在方法执行之后决定事务提交或回滚事务。

Spring的声明式事务管理可以通过两种方式实现:基于XML的方式(基于tx标签和aop名字空间)和基于注解@Transactional的方式。

2.1 基于XML方式的声明式事务

基于XML方式的声明式事务管理是通过在配置文件中配置事务规则的相关声明来实现的。Spring提供了tx命名空间来配置事务,tx命名空间下提供了<tx:advice>元素来配置事务的通知。当使用<tx:advice>元素配置了事务的增强处理后,就可以通过编写的AOP配置让Spring自动对目标生成代理。

配置<tx:advice>时,通常需要制定idtransaction-manager属性,其中id属性是配置文件中的唯一标识,transaction-manager属性用于指定一个事务管理器。除此之外,还需要配置一个<tx:attributes>子元素,在<tx:attributes>子元素中还可以配置多个<tx:method>子元素来配置执行事务的细节。如下是配置步骤:

Spring基于XML的声明式事务控制配置步骤: 1.配置事务管理器transactionManager 2.配置事务的通知<tx:advice> 此时需要引入事务的约束,tx名称空间和约束,同时还有aop的 使用<tx:advice>标签配置事务通知。 属性: id:给事务通知起一个唯一标识 transaction-manager:给事务通知指定一个事务管理器 3.配置AOP中的通用切入点表达式 4.建立事务通知和切入点表达式的对应关系 5.配置事务通知的属性:是在事务通知标签<tx:advice>的内部。

<!-- 1. 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"></bean>

<!-- 2. 配置事务的通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!-- 配置事务的属性
        isolation:用于指定事务的隔离级别。默认值是DEFAULT,表示使用数据库的默认隔离级别。
        propagation:用于指定事务的传播行为。默认值是REQUIRED,表示一定会有事务,增删改的选择。查询方法可以用SUPPORTS.
        read-only:用于指定事务是否只读,只有查询方法才能设置为true.默认是false,表示读写。
        timeout:指定事务的超时时间,默认是-1,表示永不超时。如果指定,则以秒为单位。
        rollback-for:用于指定一个异常,当产生该异常时,事务回滚,产生其他异常时,事务不回滚,没有默认值,表示任何异常都回滚。
        no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时事务回滚。没有默认值,表示任何异常都回滚。
    -->
    <tx:attributes>
        <tx:method name="find*" isolation="DEFAULT"  propagation="REQUIRED" read-only="true"  timeout="-1"/>
        <tx:method name="delete*" isolation="DEFAULT"  propagation="REQUIRED" read-only="false"  timeout="-1"/>
        <tx:method name="update*" isolation="DEFAULT"  propagation="REQUIRED" read-only="false"  timeout="-1"/>
        <tx:method name="insert*" isolation="DEFAULT"  propagation="REQUIRED" read-only="false"  timeout="-1"/>
    </tx:attributes>
</tx:advice>

<!-- 配置AOP-->
<aop:config>
    <!-- 配置切入点表达式 -->
    <aop:pointcut id="pt1" expression="execution(* com.xingze.service.impl.*.*(..))"/>
    <!--  建立切入点表达式和事务通知的对应关系-->
    <aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor>
</aop:config>

2.2 基于Annotation(注解)方式的声明式事务

Spring的声明式事务管理还可以通过Annotation(注解)的方式来实现。这种方式的使用特别简单。
第一步:在Spring容器中注册事务注解驱动

<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"></bean>

<!-- 基于注解的声明式事务,在Spring容器中注册事务注解驱动-->
<tx:annotation-driven transaction-manager="transactionManager"/>

第二步:在需要使用事务的Spring Bean类或Bean类的方法上添加注解@Transaction。如果将注解添加在Bean类上,就表示事务的设置对整个Bean类的所有方法都起作用;如果将注解添加在Bean类的某个方法上,就表示事务的设置只对该方法有效。

@Transactional(value = "",transactionManager = "",propagation = Propagation.REQUIRED,isolation = Isolation.READ_COMMITTED, readOnly = false)
public void setStudentDao(StudentDao studentDao) {
    this.studentDao = studentDao;
}

使用@Transaction注解时,可通过以下参数配置事务详情:

  • value:用于指定需要使用的事务管理器,默认为"",别名为transactionManager
  • isolation:用于指定事务的隔离级别。默认值是DEFAULT,表示使用数据库的默认隔离级别;
  • propagation:用于指定事务的传播行为。默认值是REQUIRED,表示一定会有事务,增删改的选择。查询方法可以用SUPPORTS.
  • readOnly :用于指定事务是否只读,只有查询方法才能设置为true.默认是false,表示读写。
  • timeout:指定事务的超时时间,默认是-1,表示永不超时。如果指定,则以秒为单位。
  • rollbackFor:用于指定遇到某种特定异常时强制不回滚事务。
  • rolbacForClassName
  • noRollbackFor:用于指定遇到某种特定异常时强制回滚事务。
  • noRollbackForClassName

3. Spring事务的隔离级别isolation(5种)

  • READ_UNCOMMITTED(读未提交) :一个事务读取到了另一个事务尚未提交的数据。脏读、不可重复读、幻读都有可能发生;
  • READ_COMMITTED (读已提交 ):避免脏读,但是不可重复读和幻读有可能发生
  • REPEATABLE_READ (可重复读) :避免脏读和不可重复读.但是幻读有可能发生.
  • SERIALIZABLE(串行化的) :避免以上所有读问题.
  • DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.

MySQL 默认的隔离级别:可重复读 ;Oracle:读已提交

4. Spring事务的传播行为propagation(7种)

所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。在TransactionDefinition定义中包括了如下7个表示传播行为的常量:

  • PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。(默认的)
  • PROPAGATION_SUPPORTS :如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行;
  • PROPAGATION_MANDATORY 支持当前事务,如果不存在,抛出异常
  • PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。
  • PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
  • PROPAGATION_NEVER :以非事务方式运行,如果当前存在事务,则抛出异常。
  • PROPAGATION_NESTED :如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED