当前位置: 首页 > news >正文

浅谈Mysql数据库事务操作 用mybatis操作mysql事务 再在Springboot中使用Spring事务控制mysql事务回滚

学习之前建议先复习一下事务

目录

MySql 实际开发需求

需求分析

写 sql 事务

运行 mysql 事务

Springboot 的事务框架

发起的请求

我们的传输层对象是这样的

配置事务配置类

Transactional 注解

疑问 那我们是怎么校验传入标签有误的呢


MySql 实际开发需求

需求分析

现在是有三张表

第一张表为 t_sentence 表 列有 id content create_time from hot other1 other2 other2

第二张表为 t_tags 表 列有 id name from hot other1 other2 other3 create_time

第三张表为t_sentence表和t_tags 表的中间表 t_sentence_tag 列有 id sentence_id tag_id create_time

现在我要往第一张表里插入数据 现有数据是 String 类型的 content

List<TagsReq>类型的 tags 的 name 的集合 还有 String 类型的 from

现在要求你写一个 mysql 事务

往数据库里插入数据 同时插入到 t_sentence 表和t_sentence_tag 这两张表里面

给你一个提示 要根据给出的集合中的 name 先去 t_tags 表里面把 id 查出来然后再操作

注意要保证数据一致性

现在确保的是标签一定存在 插入时间会自动赋值

因为涉及到多表操作

我们应该在操作第二张表失败后进行事务回滚

写 sql 事务

第一步是 首先插入 sentence 表 获取 sentence_id

第二步是 获取到刚刚得到的 再去 tags 表查询 tags _id

第三步是 获取到 现在有 sentence_id 和 tags_id 后 要对唯一的 sentence_id 对每一条 tags_id 的数据组合后写入中间表 sentence_tag

为保证原子性 我们需要写一个事务来处理 保证原子性

运行 mysql 事务

跑了 180ms

Springboot 的事务框架

我们将数据库操作上升到 OBM 框架

这边选择的是 mybatis

发起的请求

同样的

我们的传输层对象是这样的

请求体 JSON 格式

{ 
    "addSentenceReq": { 
        "content": "这是一句新的句子内容", 
        "from": "出处信息" 
    }, 
    "tagsList": [ 
        { 
            "name": "标签1" 
        }, 
        { 
            "name": "标签2" 
        } 
    ] 
} 

在 XML 里写了两个操作

<!-- 添加句子主记录以及插入标签关联(带事务控制) -->
<!-- 添加句子主记录 -->
<insert id="addSentence" parameterType="work.dduo.ans.model.vo.request.AddSentenceReq"
        useGeneratedKeys="true" keyProperty="sentenceId">
    INSERT INTO t_sentences
        (content, `from`, hot)
    VALUES (#{content}, #{from}, 0)
</insert>
<!-- 批量插入标签关联 -->
<insert id="batchInsertTags" parameterType="work.dduo.ans.model.vo.request.AddSentenceTagReq">
    INSERT INTO t_sentence_tag (sentence_id, tag_id)
    SELECT #{sentenceId}, id
    FROM t_tags
    WHERE `name` IN
    <foreach item="tag" collection="tagsList" open="(" separator="," close=")">
        #{tag.name}
    </foreach>
</insert>

配置事务配置类

package work.dduo.ans.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;

@Configuration
@EnableTransactionManagement
public class TransactionConfig {

    @Autowired
    private DataSource dataSource;

    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource);
    }
} 

接下来我们只需要在 Springboot 框架上封装事务处理即可

Transactional 注解

@Transactional(rollbackFor = Exception.class, timeout = 5)

捕获的是异常

service 方法

    @Transactional(rollbackFor = Exception.class,  timeout = 5)
    public boolean addSentenceWithTags(AddSentenceDTO addSentenceDTO) throws Exception {
        try {
            // 主记录插入
            AddSentenceReq addSentenceReq = addSentenceDTO.getAddSentenceReq();
            tSentencesMapper.addSentence(addSentenceReq);
            Long sentenceId = addSentenceReq.getSentenceId();
            // 关联标签插入
            List<AddTagsReq> tagsList = addSentenceDTO.getTagsList();
            AddSentenceTagReq addSentenceTagReq = new AddSentenceTagReq();
            addSentenceTagReq.setSentenceId(sentenceId);
            addSentenceTagReq.setTagsList(tagsList);
            int size = tagsList.size();
            if (!tagsList.isEmpty())  {
                int i = tSentencesMapper.batchInsertTags(addSentenceTagReq); // 返回的是改变的标签数量
                if (i != size) {
                    throw new Exception("传入无效标签");
                }
                return true;
            }
        } catch (Exception e) {
            throw e;
        }
        return false;
    }

捕获后回滚

同样超时回滚也是为了防止恶意占用 cpu mysql 出现卡死现象

疑问 那我们是怎么校验传入标签有误的呢

这边很巧妙的通过查询有用数据返回来判断的

传入 2 个标签 应该传出 2 个标签 id

如果不同的话则存在无效标签

抛出异常

被 catch 捕获

再(第二次抛出异常) 被事务注解捕获

spring 事务回滚

相关文章:

  • ‌RTSPtoWeb, 一个将rtsp转换成webrtc的开源项目
  • 银河麒麟V10SP3Server中离线安装Docker引擎与docker-compose
  • 电池预测 | 第23讲 基于CNN-BiLSTM的锂电池剩余寿命预测,附带PPT视频讲解
  • GB9706.1-2020附件J绝缘路径参考
  • Redis系列:深入理解缓存穿透、缓存击穿、缓存雪崩及其解决方案
  • 如何用AI轻松制作完美PPT,节省时间又提升效率
  • 数据结构——查找
  • 背包问题——多重背包(C语言)
  • [免费]直接整篇翻译pdf工具-支持多种语言
  • Unity导出WebGL
  • 【GPT入门】第23课 langchain serve介绍
  • 【网页】CSS原子化+变量尝试
  • test skills
  • openai 标准化协议 Structured Outputs 具体示例教程
  • Django settings.py 文件全解析
  • 案例:图书管理
  • 如何保证消息不被重复消费?(如何保证消息消费的幂等性)
  • golang-嵌套结构体
  • Unity利用噪声生成动态地形
  • vscode/windsurf/trae无法识别junit的@Test注解解决办法
  • “自己生病却让别人吃药”——抹黑中国经济解决不了美国自身问题
  • 龚正会见委内瑞拉副总统罗德里格斯
  • “中国游”带火“中国购”,“即买即退”让外国游客购物更丝滑
  • 民航局:中方航空公司一季度运输国际旅客同比大增34%
  • 白酒瓶“神似”北京第一高楼被判侵权,法院一审判赔45万并停售
  • 吏亦有道|秦汉的发明家与技术传承