Spring_声明式事务

1. Spring事务管理

1.1 编程式事务

使用原生的JDBC API进行事务管理

  1. 获取数据库连接Connection对象
  2. 取消事务的自动提交
  3. 执行操作
  4. 正常完成操作时手动提交事务
  5. 执行失败时回滚事务
  6. 关闭相关资源

1.2 声明式事务

  1. 大多数情况下声明式事务比编程式事务管理更好:它将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。
  2. 事务管理代码的固定模式作为一种横切关注点,可以通过AOP方法模块化,进而借助Spring AOP框架实现声明式事务管理。
  3. Spring在不同的事务管理API之上定义了一个抽象层,通过配置的方式使其生效,从而让应用程序开发人员不必了解事务管理API的底层实现细节,就可以使用Spring的事务管理机制。
  4. Spring既支持编程式事务管理,也支持声明式的事务管理。

1.3 Spring 声明式事务的实现

  1. 配置事务管理器
  2. 开启基于注解的声明式事务
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">


    <!--1. 开启包扫描-->
    <context:component-scan base-package="com.lz.tx"/>

    <!--2. 引入外部配置文件-->
    <context:property-placeholder location="jdbc.properties"></context:property-placeholder>

    <!--3. 配置数据源-->
    <bean id="pooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="jdbcUrl" value="${jdbc.jdbcURL}"/>
        <property name="driverClass" value="${jdbc.driverClass}"/>
    </bean>

    <!--4. 配置jdbcTemplate操作数据库-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="pooledDataSource"/>
    </bean>

    <!--5. 配置声明式事务-->
    <!--5.1 配置事务管理器-->
    <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
        <property name="dataSource" ref="pooledDataSource"/>
    </bean>
    <!--5.2 开启基于注解的声明式事务, 依赖-->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <!--5.3 给事务方法加注解-->
</beans>
  1. 给事务方法加注解

在这里插入图片描述

2. 细节问题

2.1 事务超时—timeout

@Transaction(timeout=3)
事务超出指定执行时长后自动终止并回滚

2.2 只读事务—readOnly

@Transaction(readOnly=true)
设置事务为只读事务, 进行事务优化, 加快查询速度

2.3 触发事务回滚的异常— rollbackFor, noRollbackFor

  1. 默认情况
    捕获到RuntimeException或Error时回滚,而捕获到编译时异常不回滚。
  2. 设置途径
  1. rollbackFor属性:指定遇到时必须进行回滚的异常类型,可以为多个
  2. noRollbackFor属性:指定遇到时不回滚的异常类型,可以为多个

在这里插入图片描述

2.4 隔离级别—isolation

2.4.1 事务并发问题

  1. 脏读
    [1]Transaction01将某条记录的AGE值从20修改为30。
    [2]Transaction02读取了Transaction01更新后的值:30。
    [3]Transaction01回滚,AGE值恢复到了20。
    [4]Transaction02读取到的30就是一个无效的值。
  2. 不可重复读
    [1]Transaction01读取了AGE值为20。
    [2]Transaction02将AGE值修改为30。
    [3]Transaction01再次读取AGE值为30,和第一次读取不一致。
  3. 幻读
    [1]Transaction01读取了STUDENT表中的一部分数据。
    [2]Transaction02向STUDENT表中插入了新的行。
    [3]Transaction01读取了STUDENT表时,多出了一些行。

2.4.2 隔离级别

数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题。一个事务与其他事务隔离的程度称为隔离级别。SQL标准中规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性越弱。

  1. 读未提交:READ UNCOMMITTED
    允许Transaction01读取Transaction02未提交的修改。
  2. 读已提交:READ COMMITTED
    要求Transaction01只能读取Transaction02已提交的修改。
  3. 可重复读:REPEATABLE READ
    确保Transaction01可以多次从一个字段中读取到相同的值,即Transaction01执行期间禁止其它事务对这个字段进行更新。
  4. 串行化:SERIALIZABLE
    确保Transaction01可以多次从一个表中读取到相同的行,在Transaction01执行期间,禁止其它事务对这个表进行添加、更新、删除操作。可以避免任何并发问题,但性能十分低下。

各个隔离级别解决并发问题的能力见下表
在这里插入图片描述

2.4.3 Spring 中指定事务隔离级别—isolation

在这里插入图片描述

2.5 传播行为—propagation

如果有多个事务进行嵌套运行, 子事务是否要和大事务共用一个事务.

Spring定义了7种类传播行为。常用的 REQUIRED 传播行为和 REQUIRES_NEW 传播行为

在这里插入图片描述

在这里插入图片描述

注意: 小事务设置为REQUIRED, 则小事务的其他属性来源于大事务

3. 基于XML的声明式事务配置

    <aop:config>
        <aop:pointcut id="txPoint" expression="execution(* com.lz.tx.service.*.*(..))"/>
        <aop:advisor advice-ref="myAdvice" pointcut-ref="txPoint"/>
    </aop:config>

    <tx:advice id="myAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!--指明哪些方法是事务方法-->
            <tx:method name="checkout" propagation="REQUIRES_NEW" timeout="-1"/>
            <tx:method name="get*" read-only="true"/>
        </tx:attributes>
    </tx:advice>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值