2024.10月14日-SpringMVC-基于注解声明式事务的属性

一、基于注解的声明式事务5个属性

1 只读

语法:

复制代码
@Transactional(readOnly = true)

意义:

复制代码
对一个查询操作来说,如果我们把它设置成只读,就能够明确告诉数据库,这个操作不涉及写操作。这样数据库就能够针对查询操作来进行优化
对增删改操作设置只读会抛出下面异常:Caused by: java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed

2 超时

语法:

复制代码
@Transactional(timeout = 3)

意义:

复制代码
事务在执行过程中,有可能因为遇到某些问题,导致程序卡住,从而长时间占用数据库资源。而长时间占用资源,大概率是因为程序运行出现了问题(可能是Java程序或MySQL数据库或网络连接等等)。
此时这个很可能出问题的程序应该被回滚,撤销它已做的操作,事务结束,把资源让出来,让其他正常程序可以执行。
概括来说就是一句话:超时回滚,释放资源。

3 回滚策略

声明式事务默认只针对运行时异常回滚,编译时异常不回滚。 可以通过@Transactional中相关属性设置回滚策略

  • rollbackFor属性:需要设置一个异常类的Class对象

  • rollbackForClassName属性:需要设置一个字符串类型的全类名

  • noRollbackFor属性:需要设置一个Class类型的对象

  • noRollbackFor属性:需要设置一个字符串类型的全类名

语法:

复制代码
@Transactional(noRollbackFor = ArithmeticException.class)

4 事务隔离级别

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

隔离级别一共有四种:

  • 读未提交(READ UNCOMMITTED): 允许Transaction01读取Transaction02未提交的修改。

  • 读已提交(READ COMMITTED): 要求Transaction01只能读取Transaction02已提交的修改。

  • 可重复读(REPEATABLE READ):确保Transaction01可以多次从一个字段中读取到相同的值,即Transaction01执行期间禁止其它事务对这个字段进行更新。(MySQL默认为可重复读。)

  • 串行化(SERIALIZABLE):确保Transaction01可以多次从一个表中读取到相同的行,在Transaction01执行期间,禁止其它事务对这个表进行添加、更新、删除操作。可以避免任何并发问题,但性能十分低下。

语法:

复制代码
@Transactional(isolation = Isolation.DEFAULT)//使用数据库默认的隔离级别
@Transactional(isolation = Isolation.READ_UNCOMMITTED)//读未提交
@Transactional(isolation = Isolation.READ_COMMITTED)//读已提交
@Transactional(isolation = Isolation.REPEATABLE_READ)//可重复读
@Transactional(isolation = Isolation.SERIALIZABLE)//串行化

5 事务传播

语法:

复制代码
@Transactional(propagation = Propagation.REQUIRED)

传播的概念:

复制代码
事务传播:指的是调用者将自己事务传递给被调用者,比如A.fa()里调用了B.fb():    
A.fa(){
    B.fb();
}
​
A的方式的事务传播给了B的方法事务

七个值:研究的对象是B的方法事务如何被A的方式事务影响的。 因此B的方法的设置可能是如下七个值中的一个

复制代码
1. PROPAGATION_REQUIRED:默认值    (外面影响里面,里面不影响外面)
​
    A有事务, 则B加入A的当前事务。  合成一个事务。有异常就整体回滚。
    A没有事务,B就使用自己的事务。
​
2. PROPAGATION_REQUIRES_NEW:(外面不影响里面,里面(不)影响外面)
   若A的方法有事务,  B就新建事务,使用新建的,将A的事务挂起。 如果B执行完了,A的后续代码继续使用A的事务
   若A的方法没有事务,B就新建事务,使用新建的。
​
3. PROPAGATION_NESTED :(外面的影响里面的,里面的(不)影响外面的)
    若A的方法有事务, B就在嵌套一个相同事务。
      如果B的方法抛出异常,则B回滚
      如果A的方法不捕获异常,则回滚,捕获则不回滚
      如果A的方法抛出异常,则都回滚
​
4. PROPAGATION_SUPPORTS:(外面的影响里面的,里面的影响外面的)
    如果A有事务,B就用A的事务。
         A的方法抛出异常,A和B都会回滚。
         B的方法抛出异常,A和B都会回滚。
   如果A没有事务,B就没收到事务。因此A和B都没有事务,则A和B的运行出现异常都不会回滚
    
​
5. PROPAGATION_NOT_SUPPORTED:
    如果A没有事务,B就以非事务方式执行,如果A有,B就将A传过来的事务的挂起。
   白话:  A有没有事务,B都不使用。
6. PROPAGATION_NEVER:
    如果A没有事务,就以非事务方式执行,如果有,就抛出异常。  
   白话:我都说了不要了,你非给我,我就错给你看
​
7. PROPAGATION_MANDATORY:(外面的影响里面的,里面的影响外面的)
   如果A没有事务,B就抛出异常,如果A有事务,B就使用A的当前事务。  白话:我强制需要事务,你不传给我,我就错给你看
   如果A有事务
   如果A的方法抛出异常,则A和B都会回滚
   如果B的方法抛出异常,则A和B也都会回滚
​
复制代码
Spring框架定义了七种事务传播行为:
​
•Propagation.REQUIRED•(默认):所修饰的方法必须运行在事务中。当调用方抛出异常时,被调的方法也会回滚。
•Propagation.REQUIRES_NEW•:所修饰的方法只会运行在它自己的事务中,与调用方的事务互不影响。调用方抛出异常时,被调方法不会回滚。
•Propagation.SUPPORTS•:所修饰的方法自身不运行在事务中,若调用方有事务,则运行在调用方的事务中;若无事务,则以非事务方式运行。
•Propagation.MANDATORY•:所修饰的方法必须在事务中运行。若调用方无事务,则抛出异常并回滚。
•Propagation.NOT_SUPPORTED•:以非事务方式执行操作,若当前存在事务,则将当前事务挂起。
•Propagation.NEVER•:以非事务方式运行,若调用方有事务,则抛出异常。
•Propagation.NESTED•:若调用方有事务,则嵌套事务内执行;若无事务,则执行与PROPAGATION_REQUIRED类似的操作•2。
这些传播行为帮助开发者在复杂的调用关系中更好地控制事务行为,确保数据的一致性和安全性•

二、基于XML的声明式事务

复制代码
<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-aspects</artifactId>
   <version>5.3.1</version>
</dependency>
复制代码
<!--  注册事务管理器-->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
   <property name="dataSource" ref="ds"/>
</bean>
​
<!-- tx:advice标签:配置事务通知
      id属性:给事务通知标签设置唯一标识,便于引用
      transaction-manager属性:关联事务管理器 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
   <tx:attributes>
      <!--  tx:method标签:配置具体的事务方法
                name属性:指定方法名,可以使用星号代表多个字符 -->
      
      <tx:method name="find*" read-only="true" timeout='3'/>
      <tx:method name="query*" read-only="true"/>
      <tx:method name="toUpdate*" read-only="true"/>
      
      <!--  read-only属性:设置只读属性
            rollback-for属性:设置回滚的异常 
            no-rollback-for属性:设置不回滚的异常
            isolation属性:设置事务的隔离级别
            timeout属性:设置事务的超时属性
            propagation属性:设置事务的传播行为 -->
      <tx:method name="buy*" read-only="false" rollback-for="java.lang.Exception" propagation="REQUIRED"/>
   </tx:attributes>
</tx:advice>
​
<aop:config>
   <!-- 配置事务通知和切入点表达式 -->
   <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.service.*.*(..))"></aop:advisor>
</aop:config>
​
相关推荐
Demons_kirit24 分钟前
LeetCode LCP40 心算挑战题解
java·数据结构·算法·leetcode·职场和发展
Jiaberrr1 小时前
uniapp 实现低功耗蓝牙连接并读写数据实战指南
java·前端·javascript·vue.js·struts·uni-app
家乡的落日1 小时前
一、I/O的相关概念
java
码熔burning1 小时前
【MQ篇】RabbitMQ之死信交换机!
java·分布式·rabbitmq·mq
null_equals2 小时前
Spring Cloud Stream喂饭级教程【搜集全网资料整理】
spring·kafka
黄雪超2 小时前
JVM——Java的基本类型的实现
java·开发语言·jvm
工业互联网专业2 小时前
基于web的可追溯果蔬生产过程的管理系统
java·vue.js·spring boot·毕业设计·源码·课程设计·可追溯果蔬生产过程的管理系统
程序猿大波3 小时前
基于Java,SpringBoot,HTML水文水质监测预警系统设计
java·开发语言·spring boot
海鸥813 小时前
在K8S迁移节点kubelet数据存储目录
java·kubernetes·kubelet