详解Spring事务

news2024/10/7 18:31:18

目录

1.声明式事务

1.1.概述

1.2.使用

1.2.1.建表

1.2.2.maven依赖

1.2.3.配置

1.2.4.业务

1.2.5.测试

 2.事务的传播行为


1.声明式事务

1.1.概述

spring中事务分为两种:

1.编程式事务,通过写代码来实现,每一步。

2.声明式事务,直接通过配置来实现。

常用的是声明式事务,接下来介绍的也是声明式事务。

1.2.使用

1.2.1.建表

一个用户表,有id和账户余额两个字段。

CREATE TABLE user (
    id INT(255) AUTO_INCREMENT PRIMARY KEY,
    balance INT(255)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert into user VALUES(NULL,100),(NULL,100);

1.2.2.maven依赖

<properties>
    <spring.version>5.2.0.RELEASE</spring.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- 数据库连接池 -->
    <dependency>
        <groupId>com.mchange</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.5.5</version>
    </dependency>

    <!-- 数据库驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.18</version>
    </dependency>
</dependencies>

1.2.3.配置

尤其要注意命名空间不要少引入!!!

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 数据源配置 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver" />
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/springtest?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false&amp;serverTimezone=UTC" />
        <property name="user" value="root" />
        <property name="password" value="admin" />
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg ref="dataSource" />
    </bean>
    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    <!--开启注解扫描-->
    <context:component-scan base-package="com.eryi.service"></context:component-scan>

    <!-- 启用事务注解 -->
    <tx:annotation-driven transaction-manager="transactionManager" />
</beans>

1.2.4.业务

这里模拟id为1的用户向id为2的用户转账100块,转账有两步组成:

  • id为1的用户账户扣100块
  • id为2的用户账户增加100块

在两步中模拟一个异常,导致只有只完成了id为1的用户扣100块的SQL执行了,但是id为2的用户增加100块的SQL没有执行。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

@Component
public class UserService {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Transactional
    public void transfer(){
        try {
            // 从 fromUserId 账户中扣除金额
            jdbcTemplate.update("update user set balance = balance - ? where id = ?", 100, 1);

            // 抛出异常,测试事务是否回滚
            int i = 1 / 0;

            // 将金额转入 toUserId 账户中
            jdbcTemplate.update("update user set balance = balance + ? where id = ?", 100, 2);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

1.2.5.测试

public static void main(String[] args) {
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = applicationContext.getBean("userService", UserService.class);
        userService.transfer();
    }

如果没有事务的话,会是这种情况:

 有了事务的话,事务中所有SQL会具有原子性,要么全部成功,要么全部失败,会是这个结果:

 2.事务的传播行为

Spring中存在着一个概念——事务的传播行为。事务的传播行为指的是一个事务方法被另一个事务方法调用,即嵌套事务,出现异常该怎么回滚。 

Spring规定有7种事务的传播行为:

required如果出现异常的方法有事务就用这个事务,没有的话再去用其他的事务。例如:方法A调用方法B,如果B出现异常,B有事务就用B的事务,B没有事务,才会去用A的事务(只要有一个回滚,整体就会回滚)
requires_new如果当前有事务,就用当前事务,否则就重新开一个事务。例如:方法A调用方法B,如果B出现异常,B有事务就用B的事务,B没有事务,就会去新建一个事务,最后效果是B会回滚,但是A不会回滚。
supports当前没有事务,就以非事务运行。当前有事务呢?就以当前事务运行。
mandatory其他没有事务就会抛异常。当前没有事务抛出异常,当前有事务则支持当前事务。
not_supported以非事务执行。
never以非事务执行,如果存在事务,抛出异常。
nested如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行单独地提交或回滚。

这里附上一篇其它博主对于七种事务的传播属性的介绍,其中有详细的代码示例和讲解,很清晰:

Spring事务传播行为_荠菜煎包的博客-CSDN博客

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

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

相关文章

华为手表开发:WATCH 3 Pro(15)传感器订阅加速度计

华为手表开发&#xff1a;WATCH 3 Pro&#xff08;15&#xff09;传感器订阅加速度计初环境与设备加速度传感器介绍与说明鸿蒙开发文件夹&#xff1a;文件重点新增展示的文本标记index.hmlindex.cssindex.js初 希望能写一些简单的教程和案例分享给需要的人 鸿蒙可穿戴开发 环…

Elasticsearch:索引状态是红色还是黄色?为什么?

在我之前文章 “Elasticsearch&#xff1a;如何调试集群状态 - 定位错误信息” 中&#xff0c;我有详细介绍如何调试集群状态。在今天的文章中&#xff0c;我将详细介绍如何故障排除和修复索引状态。 Elasticsearch 是一个伟大而强大的系统&#xff0c;特别是创建一个可扩展性极…

C++、STL标准模板库和泛型编程 ——关联式容器 (侯捷)

C、STL标准模板库和泛型编程——关联式容器 &#xff08;侯捷&#xff09;&#xff08; 持续更新&#xff01;&#xff01;&#xff01;&#xff09; 关联式容器rb_tree 容器set、multiset 容器map、multimap容器C、STL标准模板库和泛型编程——序列式容器 &#xff08;侯捷&am…

go+vue——go入门

govue技术选择入坑理由需要搭建前后端&#xff0c;Java 0 基础 &#xff0c;环境容易出现问题&#xff1b;GO上手快&#xff0c;问题少推荐&#xff1a;【七米】代码博客搭建Go语言开发环境下载 并 安装检查是否安装好&#xff1f;GOPROXY 非常重要&#xff08;帮你下载国外、G…

分布式锁Redision

目录 1.ab工具(压测工具)的安装 2.前置 3.优化 3.1synchronized修饰代码方法/代码块 3.2分布式锁事务的解决方案 3.3Redis实现锁问题 3.3.1 set ex方式 3.3.2 set ex方式设置过期时间 3.3.3单redis结点的解决UUID和LUA脚本 3.3.4redission解决分布式锁 4.Redission解…

数据结构:顺序表

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下数据结构方面有关顺序表的相关知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C语言专栏&#xff1a;C语言&#xff1a;从入门…

阿里的Leader为什么牛逼?秘密都在“三板斧”里...

许多人都觉得&#xff0c;啊里出来的Leader&#xff0c;做事情都很有方法、有套路、有结果&#xff0c;秘密究竟在哪里&#xff1f;其实一个人的牛逼&#xff0c;首先是方法论的牛逼。本文就来聊聊&#xff0c;阿里Leader们都要学习的管理方法论&#xff0c;俗称阿里“三板斧”…

《MySQL系列-InnoDB引擎37》索引与算法-全文检索

全文检索 1 概述 对于B树的特点&#xff0c;可以通过索引字段的前缀进行查找。例如如下的查询方式是支持B树索引的,只要name字段添加了B树索引&#xff0c;就可以利用索引快速查找以XXX开头的名称。 select * from table where name like XXX%; 而如下这种情况不适合私有B索…

BUUCTF-sql注入联合查询的创建虚拟表-词频-steghide的使用

第七周第三次 目录 WEB [GXYCTF2019]BabySQli [GXYCTF2019]BabyUpload Crypto 世上无难事 old-fashion ​Misc 面具下的flag 九连环 WEB [GXYCTF2019]BabySQli 这是一道很新的题目 我们打开环境 发现登入注册界面 先看看源码有没有提示 发现有一个 php文件 进入…

Spark 对hadoopnamenode-log文件进行数据清洗并存入mysql数据库

一.查找需要清洗的文件 1.1查看hadoopnamenode-log文件位置 1.2 开启Hadoop集群和Hive元数据、Hive远程连接 具体如何开启可以看我之前的文章&#xff1a;(10条消息) SparkSQL-liunx系统Spark连接Hive_难以言喻wyy的博客-CSDN博客 1.3 将这个文件传入到hdfs中&#xff1a; hd…

OpenAI Translator | 基于ChatGPT API全局翻译润色解析及ORC上传图像翻译插件

简介 OpenAI Translator&#xff0c;一款基于 ChatGPT API 的划词翻译的浏览器插件和跨平台桌面端应用&#xff0c;使用 ChatGPT API 进行划词翻译和文本润色&#xff0c;借助了 ChatGPT 强大的翻译能力&#xff0c;帮助用户更流畅地阅读外语和编辑外语&#xff0c;允许跨 55 …

Qt音视频开发35-左右通道音量计算和音量不同范围值的转换

一、前言 视频文件一般会有两个声音通道及左右声道&#xff0c;值有时候一样有时候不一样&#xff0c;很多场景下我们需要对其分开计算不同的音量值&#xff0c;在QAudioFormat中可以获取具体有几个通道&#xff0c;如果是一个通道&#xff0c;则左右通道值设定一样&#xff0…

【时序数据库】时间序列数据和MongoDB第三部分-查询、分析和呈现时间序列数据...

在《时间序列数据和MongoDB:第1部分-简介》「时序数据库」时间序列数据与MongoDB&#xff1a;第一部分-简介中&#xff0c;我们回顾了理解数据库的查询访问模式需要询问的关键问题。在《时间序列数据和MongoDB:第2部分-模式设计最佳实践》「时序数据库」时序数据库和MongoDB第二…

Java实验课的学习笔记(二)类的简单使用

本文章就讲的是很基础的类的使用 重点大概就是类的构造函数以及一些很基础的东西。 实验内容是些老生常谈的东西&#xff0c;Complex类&#xff0c;在当初学C面向对象的时候也是这个样子展开的。 内容如以下&#xff1a; public class Complex {float real;float imag;public…

APK瘦身

先看下APK打包流程&#xff1a;APK打包流程_贺兰猪的博客-CSDN博客 知道了APK打包流程后想要瘦身&#xff0c;其实无非就是把整个APK的一些文件进行一个瘦身。 看下apk的这个文件。包括class、资源&#xff0c;资源生成arsc(资源映射表)&#xff0c;manifest清单&#xff0c;…

快排(非递归)及计数排序算法

都学了递归版的快速排序为何还要再学非递归实现&#xff1f;由于在递归过程中&#xff0c;如果数据量过大&#xff0c;那么实现时容易导致栈溢出&#xff0c;虽然代码没有问题&#xff0c;但是就是会崩&#xff0c;因此要将其改为非递归来实现 文章目录一、快速排序&#xff08…

如何使用Mac远程控制Windows电脑?

在你开始之前&#xff0c;设置您要远程处理的 Windows 计算机。 先安装 Microsoft Remote Desktop。 您可以在“应用程序”文件夹中检查它。 如果在个人计算机上安装&#xff0c;请转到 Apple App Store 并下载 Microsoft Remote Desktop。 如果在 TXST 计算机上安装&#xff0…

【C语言】递归解决经典题目(汉诺塔问题、青蛙跳台阶问题)

简单不先于复杂&#xff0c;而是在复杂之后。 目录 1. 汉诺塔问题 1.1 简介及思路 1.2 代码实现 2. 青蛙跳台阶问题 2.1 简介及思路 2.2 代码实现 1. 汉诺塔问题 1.1 简介及思路 汉诺塔问题是一种经典的递归问题&#xff0c;起源于印度传说中的塔 of Brahma。问题描…

手把手教你学习IEC104协议和编程实现 十 故障事件与复位进程

故障事件 目的 在IEC104普遍应用之前,据我了解多个协议,再综合自动化协议中,有这么一个概念叫“事故追忆”,意思是当变电站出现事故的时候,不但要记录事故的时间,还需记录事故前后模拟量的数据,从而能从一定程度上分析事故产生的原因,这个模拟量就是和今天讲解的故障…

silvaco 仿真BJT

本次实验为利用silvaco仿真BJT器件&#xff0c;分析不同p区厚度以及p区不同掺杂浓度研究其电流增益的变化。 一、器件要求 区域 掺杂方式 掺杂浓度或 峰值浓度&#xff08;/cm3&#xff09; 厚度&#xff08;um&#xff09; 宽度&#xff08;um&#xff09; N-漂移区 均匀…