03. Spring 事务管理

news2024/11/16 1:46:57

文章目录

  • 1. Spring 事务管理简介
  • 2. @Transactional 注解属性信息
  • 3. @Transactional 简单使用
  • 4. @Transactional 使用注意事项
    • 4.1 正确指定事务回滚的异常类型
      • 4.1.1 Java 异常继承体系
    • 4.2 `@Transactional` 注解应用在 `public` 方法或类上才有效
    • 4.3 正确设置 `@Transactional` 的 `propagation` 属性。
      • 4.3.1 事务的传播行为
      • 4.3.2 `TransactionDefinition` 和 `Propagation`
  • 5. Spring 事务失效的场景
    • 5.1 @Transactional 注解使用在非 public 方法上,导致事务失效
    • 5.2 propagation 参数设置错误,导致事务失效
    • 5.3 rollbackFor 参数设置错误,导致事务失效
    • 5.4 在同一个类中,方法之间的相互调用导致事务失效
    • 5.5 异常被捕获导致事务失效
    • 5.6 数据库引擎不支持事务

1. Spring 事务管理简介

事务管理是应用系统开发中必不可少的一部分,Spring 为事务管理提供了丰富的功能。Spring 的事务管理分为编程式和声明式两种方式。声明式事务管理可以使业务代码逻辑不受污染,将业务逻辑和事务处理解耦。声明式事务也有两种方式:一种是在配置文件(xml)中做相关的事务规则声明,一种是基于注解 @Transactional 的方式

事务是数据库的概念,Spring 本身是没有事务的,Spring 的事务是借助 AOP,通过动态代理的方式实现。
在我们要操作数据库的时候,实际是 Spring 通过动态代理进行功能拓展,在我们的代码操作数据库之前通过数据库客户端打开数据库事务,如果代码执行完毕没有异常信息或者是没有 Spring 要捕获的异常信息时,再通过数据库客户端提交事务;如果有异常信息或者是有 Spring 要捕获的异常信息,再通过数据库客户端程序回滚事务,从而控制数据库事务。

Spring 基于注解使用事务主要有两步:

  • 在主配置类上声明 @EnableTransactionManagement 注解,表示开启声明式事务;
  • 在访问数据库的方法上添加 @Transactional 注解。

@Transactional 注解也可以用在类上,表示该类的所有公共方法都配置相同的事务属性。如果类和方法都配置了 @Transactional,应用程序会用方法级别的事务属性来管理事务。

2. @Transactional 注解属性信息

属性名说明
name当配置文件中有多个 TransactionManager时,可以用该属性指定选择哪个事务管理器
propagation事务的传播行为,默认值:REQUIRED
isolation事务的隔离度,默认值:DEFAULT
timeout事务的超时时间,默认值 -1。如果超过该时间但事务未完成,则回滚该事务
readOnly指定事务为只读事务,默认值 false。指定当前事务为只读事务后,当前事务不能进行写操作,否则报错
rollbackFor指定能够触发事务回滚的异常类型,如果有多个异常类型要指定,用逗号分隔
noRollbackFor抛出该参数指定的异常类型,不回滚事务

3. @Transactional 简单使用

如下有一个保存数据的方法,加上 @Transactional 注解,运行时抛出运行时异常之后,事务会自动回滚,数据不会插入数据库。

    @Override
    @Transactional
    public boolean save() {
        boolean res = stateRepository.save();
        if(true) {
            throw new RuntimeException();
        }
        return res;
    }
  • 如果去掉 @Transactional 注解,save() 就是一个普通的没有事务的方法,执行时还是会抛出异常,但是会插入数据。
  • 如果加上 @Transactional 注解,但是在方法内使用 try-catch 捕获异常,则事务不会回滚,数据会插入成功。
        @Override
        @Transactional
        public boolean save() {
            boolean res = stateRepository.save();
            try {
                if(true) {
                    throw new RuntimeException();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
            return res;
        }
    

4. @Transactional 使用注意事项

4.1 正确指定事务回滚的异常类型

默认情况下,@Transactional 会在运行时异常及其子类异常时回滚事务,其他类型的异常 Spring 不会帮我们回滚事务。如果要在指定类型的异常时回滚事务,需要使用 rollbackFor 指定异常类型,如 @Transacrional(rollbackFor = Exception.class)

4.1.1 Java 异常继承体系

在这里插入图片描述
最顶层的异常类型是可抛出异常 Throwable,有 ErrorException 两个子类。

  • Error 表示严重的错误(如 OOM);
  • Exception 分为 运行时异常(RuntimeException)和非运行时异常;
  • 非运行时异常是检查异常(checked exceptions),编译阶段就能检查出来,编码时需要 try-catch 或抛出异常。
  • Error 和运行时异常是非检查异常(unchecked exceptions),编译阶段不会检查。

4.2 @Transactional 注解应用在 public 方法或类上才有效

只有 @Transactional 注解应用到 public 方法,才能进行事务管理。

4.3 正确设置 @Transactionalpropagation 属性。

propagation 属性用于指定事务的传播行为,当 propagation 参数指定为 SUPPORTSNOT_SUPPORTEDNEVER 时,事务将不会发生回滚。

4.3.1 事务的传播行为

事务的传播行为是指,多个事务方法相互调用时,事务如何在这些方法之间传播。

Spring 支持一下 7 种事务传播行为,定义在枚举类 Propagation

传播类型说明
REQUIRED(默认值)支持当前事务,如果有就加入当前事务中。如果当前方法没有事务,则新建一个事务
SUPPORTS支持当前事务,如果有就加入当前事务中。如果当前方法没有事务,则以非事务方式执行
MANDATORY支持当前事务,如果有就加入当前事务中。如果当前方法没有事务,就抛出异常
REQUIRES_NEW如果当前存在事务,就把当前事务挂起,然后新建一个事务;如果当前方法不存在事务,就新建一个事务
NOT_SUPPORTED以非事务方式执行,如果当前方法存在事务就挂起当前事务,执行完后恢复事务
NEVER以非事务方式执行,如果当前方法存在事务,则抛出异常
NESTED如果当前存在事务,则嵌套在当前事务中。如果当前没有事务,则新建一个事务自己执行。(嵌套事务使用保存点作为回滚点,内部事务回滚不影响外部事务的提交,但是外部事务的回滚会把内部事务一起回滚。)

4.3.2 TransactionDefinitionPropagation

TransactionDefinition 和 Propagation 是 Spring 框架中两个不同的概念,它们在事务管理中起着不同的作用。

  • TransactionDefinition 是一个接口,它定义了事务的基本属性,如隔离级别、传播行为、超时时间等。它允许您为事务设置各种属性,并将这些属性应用于事务管理器。
  • Propagation是一个枚举,它定义了事务的传播行为。事务传播行为确定了当一个事务方法被另一个事务方法调用时会发生什么。它控制了事务如何与现有事务相关联,以及是否创建新的事务。
  • 总之,TransactionDefinition 是关于定义事务属性的,而 Propagation 是关于控制事务传播行为的。它们在 Spring 框架的事务管理中发挥着重要作用,使开发人员能够精细地控制事务的行为。

5. Spring 事务失效的场景

5.1 @Transactional 注解使用在非 public 方法上,导致事务失效

5.2 propagation 参数设置错误,导致事务失效

propagation 参数设置为 SUPPORTSNOT_SUPPORTEDNEVER 时,@Transactional 注解就不会产生效果。

5.3 rollbackFor 参数设置错误,导致事务失效

  • Spring 默认在方法抛出未检查异常或 Error 时回滚事务,其他异常类型不会回滚;
  • 如果要在方法抛出其他异常时也能回滚事务,需要 rollbackFor 参数指定异常类型。

5.4 在同一个类中,方法之间的相互调用导致事务失效

如下,在 StateService 中有两个保存方法:

	@Override
    @Transactional
    public boolean save() {
    	save2();
        boolean res = stateRepository.save();
        if(true) {
            throw new RuntimeException();
        }
        return res;
    }
    
    private boolean save2() {
        StateDAO stateDAO = new StateDAO();
        stateDAO.setWorkspaceKey("space1");
        return stateRepository.saveState(stateDAO);
    }

save() 方法首先调用了 save2() 方法,然后 save() 方法抛出异常,导致事务回滚,两条数据都不会插入数据库。

现在我们想实现:save() 方法抛异常不影响 save2() 方法插入数据。@Transactionalpropagation 参数可以设置事务的传播行为,我们可以尝试给 save2() 方法设置 propagation = REQUIRES_NEW 去实现。如下:

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public boolean save() {
    	save2();
        boolean res = stateRepository.save();
        if(true) {
            throw new RuntimeException();
        }
        return res;
    }
    
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    private boolean save2() {
        StateDAO stateDAO = new StateDAO();
        stateDAO.setWorkspaceKey("space1");
        return stateRepository.saveState(stateDAO);
    }

但是,运行之后,发现 save2() 方法的数据也没有插入数据库。

原因:

在默认的代理模式下,只有目标方法由外部调用,才能被 Spring 的事务拦截器拦截。在同一个类的两个方法直接调用,不会被 Spring 的事务拦截器,也就是说 save2() 方法的 @Transactional 注解是失效的。

为解决该问题,可以新建一个 service 类,提供 save2() 方法。然后在 save() 方法中调用这个外部的 save2() 方法。

5.5 异常被捕获导致事务失效

事务通知只有捕获到了目标抛出的异常,才能进行回滚处理;如果目标自己处理掉异常,事务通知无法知悉。

如:

    @Override
    @Transactional
    public boolean save() {
        boolean res = planBaselineStateRepository.save();
        try {
            if(true) {
                throw new RuntimeException();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return res;
    }

5.6 数据库引擎不支持事务

  • InnoDB 引擎支持事务,是 MySQL 默认的引擎;
  • MyIsam 引擎不支持事务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1701563.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Spring】深入理解 Spring 状态机:简化复杂业务逻辑的利器

前言 在软件开发中,有许多场景需要处理状态转换和状态驱动的逻辑,比如订单处理、工作流程管理、游戏引擎等。Spring 状态机(Spring State Machine)是 Spring Framework 提供的一个强大的模块,用于帮助开发人员轻松构建…

【VTKExamples::Utilities】第二期 AnimationScene

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享VTK样例AnimationScene,并解析VTK中动画的基本框架,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ…

OSCP学习,布置你的Kali Linux

为什么要写这篇文章? 我是一个OSCP学习者,以教促学。同时也能让各位入门的师傅们更好的了解OSCP这门课程。本人文笔不太好,如果有什么写的不对的地方,师傅们多多指正。 参考资料: OSCP 考试电子书 Linux Basics for…

微信小程序毕业设计-跑腿系统项目开发实战(附源码+演示视频+LW)

大家好!我是程序猿老A,感谢您阅读本文,欢迎一键三连哦。 💞当前专栏:微信小程序毕业设计 精彩专栏推荐👇🏻👇🏻👇🏻 🎀 Python毕业设计…

深度学习之加宽全连接

1.Functional API 搭建神经网络模型 1.1.利用Functional API编写宽深神经网络模型进行手写数字识别 import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.datasets import load_iris from sklearn.model_selection import train_test_spli…

工程技术SCI期刊,中科院4区,收稿范围非常广泛,审稿快易录用!

一、期刊名称 CMES-Computer Modeling in Engineering & Sciences 二、期刊简介概况 期刊类型:SCI 学科领域:工程技术 影响因子:2.4 中科院分区:4区 三、期刊征稿范围 本期刊在工程与科学的计算机建模领域发表具有合理永…

python中的空语句以及对于条件语句的总结

if条件: 代码块 if条件: 代码块1 else: 代码块2 if条件1: 代码块1 elif条件2: 代码块2 else: 代码块3

2016届蓝桥杯大赛软件类国赛Java大学B组 愤怒小鸟 数学模拟

注意开浮点数 ​​​​ import java.util.Scanner;public class Main {static Scanner scnew Scanner(System.in);public static void main(String[] args) {double t0;int cnt0;double distance1000;while(distance>1){//相撞时间tdistance/60.0;distance-t*20;cnt;}Syste…

梭住绿色,植梦WILL来,容声冰箱“节能森林计划”再启航

近日,容声冰箱再度开启了“节能森林计划”绿色公益之旅。 据「TMT星球」了解,此次活动深入到阿拉善荒漠化地带,通过实地考察和亲身体验,见证容声了“节能森林计划”项目的持续落地和实施效果。 2022年,容声冰箱启动了…

IP地址在广告行业中的重要地位

新时代,广告已经成为了企业推广产品的必要手段,而企业想要广告效果好,就要做到精准投放营销广告,将“花钱”的广告精准送到产品的受众用户面前,让收益大于花销,而归根究底就是广告转化率与回报率是否达到预…

Kivy 项目51斩百词 6 播放读音

为了给小喇叭图像绑定点击事件,实现当用户点击按钮时,触发该事件对应的回调方法。 在方法内对于不同的系统Kivy使用不同的播放语音方法, 对于Windows系统 使用SoundLoader播放语音, 对于其他的Unix系统 使用Pyjnjus播放…

PawSQL: 企业级SQL审核工具的新玩家

随着数据库应用在企业中的广泛使用,确保SQL代码质量的重要性日益凸显。现有的SQL审核工具很多,包括Yearning、goInception、Bytebase、爱可生的SQLE、云和恩墨的SQM等等,但是它们或者规则覆盖度、或者是在正确率等方面存在明显不足&#xff1…

Halo Theme AirCloud 主题文档

发现一款简洁的halo主题 Halo Theme AirCloud 主题文档 | LogDicthttps://www.logdict.com/archives/AirCloud

2-Django项目进阶--继续学生管理系统

目录 项目框架: urls.py views.py modules.py class_data.html add_and_modify.html add_stu.html 笔记: 继承语法 模板继承总结: 班级添加 add_and_modify.html 修改添加公用一个页面即可 views.py 班级修改 views.py url.py 班级删除 views.py…

牛客热题:寻找第K大

📟作者主页:慢热的陕西人 🌴专栏链接:力扣刷题日记 📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言 文章目录 牛客热题:寻找第K大题目链接方法一&#…

面试官:讲讲为什么SpringBoot的 jar 可以直接运行?

Spring Boot 是一个用于简化 Spring 应用程序开发的框架,它通过约定优于配置和大量的自动化配置,使得开发者可以更轻松地创建和部署 Spring 应用程序。一个特别引人注目的特性是 Spring Boot 应用可以打包成一个可执行的 JAR 文件,并且可以直…

基于图鸟UI的圈子商圈:一个全栈前端模板的探索与应用

摘要: 本文介绍了一个基于图鸟UI的纯前端模板——圈子商圈,它支持微信小程序、APP和H5等多平台开发。该模板不仅包含丰富的UI组件和页面模板,还提供了详尽的使用文档,旨在帮助开发者快速构建出酷炫且功能齐全的前端应用。本文将从…

51-54 Sora能制作动作大片还需要一段时间 | DrivingGaussian:周围动态自动驾驶场景的复合高斯飞溅

24年3月,北大、谷歌和加州大学共同发布了DrivingGaussian: Composite Gaussian Splatting for Surrounding Dynamic Autonomous Driving Scenes。视图合成和可控模拟可以生成自动驾驶的极端场景Corner Case,这些安全关键情况有助于以更低成本验证和增强自…

第14章-蓝牙遥控小车 手把手做蓝牙APP遥控小车 蓝牙串口通讯讲解

本文讲解手机蓝牙如何遥控小车,如何编写串口通信指令 第14章-手机遥控功能 我们要实现蓝牙遥控功能,蓝牙遥控功能要使用:1.单片机的串口、2.蓝牙通信模块 所以我们先调试好:单片机的串口->蓝牙模块->接到一起联调 14.1-电脑控制小车 完成功能…

乐游巴蜀,V你而来!苏州金龙海格新V系很“巴适”

成都,自古有“天府之国”之美誉,古老的城市人文与现代的摩登活力相交相融,加之令人垂涎的美食文化,共同造就了这里超强的旅游吸引力。2024年5月23日,以“用心前行,V你而来”为题的苏州金龙新V系客车推介会走…