Spring_Day4_事务、Spring管理事务、声明式事务

spring声明事务

事务

在一次业务操作中的所有增删改都应该都成功,要么都失败

如果其中的一次操作执行失败,则应该回滚到没执行的状态

事务的四大特性

事务特性含义
原子性(Atomicity)事务是工作的最小单元,整个工作单元要么全部执行成功,要么全部执行失败
一致性(Consistency)事务执行前与执行后,数据库中数据应该保持相同的状态。如:转账前总金额与转账后总金额相同。
隔离性(Isolation)事务与事务之间不能互相影响,必须保持隔离性。
持久性(Durability)如果事务执行成功,对数据库的操作是持久的。

事务并发访问的问题

  • 脏读: 一个事务(用户)读取到了另一个事务没有提交的数据

  • 不可重复读:当别人的事务修改提交了数据后,在我们的事务中在修改前和修改后查询出现了不同的数据

  • 幻读:在一次事务中,多次读取到的条数不一致

事务的隔离级别

级别名字隔离级别脏读不可重复读幻读数据库默认隔离级别
1读未提交read uncommitted
2读已提交read committedOracle和SQL Server
3可重复读repeatable readMySQL
4串行化serializable

可重复读会触发幻读的两种情况:在我方事务进行修改后再查询会出现另一方的数据

在我方插入的数据与另一方提交插入的数据主键冲突时会插入失败

串行化:把读取的数据或者修改的数据加上读锁或写锁

(根据主键列作为索引会触发行锁,非主键列作为索引会触发表锁)

当一方事务在读的过程中,另一方事务无法进行写操作

当一方事务在写的过程中,另一方事务无法进行读写操作(Ctrl+C停止)

查询事务隔离级别

select @@tx_isolation;

设置事务隔离级别(需要重启客户端会话)

set global transaction isolation level 四种隔离;
​
set global transaction isolation level read uncommitted;
set global transaction isolation level read committed;
set global transaction isolation level repeatable read;
set global transaction isolation level serializable;

开启事务

start transaction;
或者
begin;

提交事务

commit;

回滚事务

rollback;

Spring事务管理

编程式事务(不符合高内聚低耦合)

将事务管理代码写入到业务方法中,对核心业务代码的侵入性太大

可以以代码块的级别开启事务

声明式事务

AOP非常适合管理事务,通过声明表达式拦截需要事务管理的方法

声明式事务避免了对核心事务的入侵

不足:开启事务的级别最细的级别只能做到方法级别,无法做到编程式的代码块级别

Spring事务管理器

所有的事务管理器的都继承自org.springframework.transaction.PlatformTransactionManager接口。

  • 事务管理器主要的实现:

  • DataSourceTransactionManager:使用Spring JDBC 或 Mybatis 等基于DataSource数据源的持久化技术时,使用 该事务管理器

  • JpaTransactionManager:使用JPA时采用的事务管理器

  • JtaTransactionManager:具有多个数据源的全局事务使用该事务管理器

  • JdoTransactionManager:使用JDO进行持久化时 ,使用该事务管理器

  • HibernateTransactionManager:使用Hibernate进行持久化时,使用该事务管理器

事务传播行为

Spring定义了7种类传播行为,在org.springframework.transaction.TransactionDefinition类中被定义。

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

TransactionDefinition类中不仅定义了事务的传播行为,也定义了很多事务的隔离级别:

静态常量说明
ISOLATION_DEFAULT使用数据库默认的隔离级别,Spring默认值
ISOLATION_READ_UNCOMMITTED读未提交
ISOLATION_READ_COMMITTED读已提交
ISOLATION_REPEATABLE_READ可重复读
ISOLATION_SERIALIZABLE串行化

实现事务管理器

默认是:编译式异常不会回滚,运行式异常会回滚

XML

配置事务管理器及事务通知

<!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--引用数据源-->
        <property name="dataSource" ref="dataSource"/>
    </bean>
​
    <!--配置事务通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
​
            <!--
                isolation:事务隔离级别
                    DEFAULT:使用数据库默认的隔离级别(默认值)
                    READ_UNCOMMITTED:读未提交
                    READ_COMMITTED:读已提交
                    REPEATABLE_READ:可重复读
                    SERIALIZABLE:串行化
                propagation: 事务传播行为
                    REQUIRED:必须要有事务,如果已经存在事务,则加入到这个事务中,如果没有事务则创建一个新的事务
                    SUPPORTS:支持当前事务,如果调用这个方法之前没有事务则不会开启新的事务
                    MANDATORY:必须存在事务,如果调用此方法之前没有事务,就抛出异常
                    REQUIRES_NEW:新建事务,如果调用此方法之前就已经开启过事务,则将之前的事务挂起
                    NOT_SUPPORTED:非事务方式,如果调用此方法之前就存在事务,则挂起事务
                    NEVER:非事务方式运行,如果调用此方法之前存在事务,则抛出异常
                    NESTED:如果存在事务,则嵌套在事务内执行,如果没有事务则与REQUIRED保存一致
               read-only: 是否只读
                    true: 只读
                    false:非只读(默认值)
               timeout: 方法执行超时时间,默认值为-1,代表永不超时,单位为秒
               rollback-for: 指定特定的异常才回滚(默认情况下,任何的运行时异常事务都会回滚,但编译时异常都不会进行回滚),该配置针对于编译时异常;可以写多个,以逗号隔开
​
               no-rollback-for: 指定一个特定的异常事务不回滚,可以写多个,以逗号隔开
​
            -->
<!--            <tx:method name="query*" isolation="DEFAULT"
                       propagation="REQUIRED" read-only="true" timeout="3"
                       rollback-for="java.lang.NullPointerException,java.lang.ClassCastException"
                       no-rollback-for="java.lang.ArithmeticException"  />
                  -->
<!--            <tx:method name="query*" read-only="true"/>-->
<!--            <tx:method name="select*" read-only="true"/>-->
<!--            <tx:method name="query*" read-only="true"/>-->
<!--            <tx:method name="save*" read-only="true"/>-->
<!--            <tx:method name="insert*" />-->
<!--            <tx:method name="add*" />-->
<!--            <tx:method name="update*" />-->
<!--            <tx:method name="modify*" />-->
<!--            <tx:method name="delete*" />-->
<!--            <tx:method name="remove*" />-->
            <!--出现ArithmeticException异常不回滚-->
            <tx:method name="transfer" no-rollback-for="java.lang.ArithmeticException"/>
        </tx:attributes>
​
    </tx:advice>
  • no-rollback-for:指定什么异常不回滚(该配置只针对于运行时异常),可以写多个,以逗号隔开;

    • no-rollback-for指定的参数是Exception:则代表Java中的任何异常都不回滚,

  • rollback-for:指定什么异常要回滚(该配置针对于编译时异常);可以写多个,以逗号隔开;

    • rollback-for指定的参数是Exception:则Java中任何的异常都回滚;

开启事务注解驱动

<!--
        开启事务注解驱动
        transaction-manager: 指定事务管理的名称,默认为transactionManager
    -->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

注解

配置事务管理器及事务通知

@Transactional(
            transactionManager = "transactionManager",              // 事务管理器的名称
            propagation = Propagation.REQUIRED,                     // 传播行为
            isolation = Isolation.DEFAULT,                          // 隔离级别
            timeout = 3000,                                         // 超时时间
            readOnly = false,                                       // 是否只读
            rollbackFor = {MyException.class},                      // 出现该异常回滚
            noRollbackFor = {ArithmeticException.class}             // 出现指定异常不回滚
    ) 

作用范围:

  • 可以添加在方法上,对特定的方法开启事务管理。

  • 也可以添加在类级别上,此时该类中的所有 public 方法都会被事务管理。

开启事务注解驱动

@EnableTransactionManagement

它告诉 Spring 容器开启对声明式事务的支持。当在 Spring 配置类上添加了这个注解后,Spring 会自动扫描被@Transactional注解标记的方法和类,并为它们提供事务管理功能。

Spring 在启动时会解析带有@EnableTransactionManagement注解的配置类,并根据配置创建事务管理器和事务拦截器。事务拦截器会拦截被@Transactional注解标记的方法调用,在方法执行前后进行事务的开启、提交或回滚操作。

一、mode 属性

  1. 作用:用于指定事务管理的模式。

  2. 可选值:

    • AdviceMode.PROXY(默认值):使用代理模式实现事务管理。Spring 会为被@Transactional注解的目标对象创建一个代理对象,在代理对象中拦截方法调用并进行事务处理。这是最常用的模式,适用于大多数情况。

    • AdviceMode.ASPECTJ:使用 AspectJ 实现事务管理。这种模式需要在项目中引入 AspectJ 相关的库,并进行额外的配置。AspectJ 方式可以在不使用代理的情况下实现事务管理,对于某些复杂的场景可能更有优势,但配置相对复杂一些。

二、order 属性

  1. 作用:用于指定事务通知在 Spring AOP 通知链中的顺序。

  2. 说明:当有多个 AOP 通知(如事务通知、安全通知等)同时存在时,通过设置order属性可以控制它们的执行顺序。较小的值表示较高的优先级,即先执行。

import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;
​
@Configuration
@EnableTransactionManagement(mode = AdviceMode.ASPECTJ, order = 1)
public class AppConfig implements TransactionManagementConfigurer {
    // 其他配置...
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值