MybatisPlus(5)

news2025/1/12 12:30:32

前言🍭

❤️❤️❤️SSM专栏更新中,各位大佬觉得写得不错,支持一下,感谢了!❤️❤️❤️

Spring + Spring MVC + MyBatis_冷兮雪的博客-CSDN博客

上篇讲了增删的操作,这篇讲修改操作中的一个问题以及它对应的解决方案——乐观锁,还有代码生成器的实现。

一、乐观锁(update)🍭

业务并发现象带来的问题: 秒杀。

我们应该都遇过买东西限量秒杀吧,这个时候这么多人一起抢,我们应该怎么去实现秒杀程序呢?

下面我们会讲解2000访问量的秒杀实现,如果是更多人的话就应该使用其他更好的方法了。

1、添加字段和实体类属性🍉

添加version字段,默认值为1

 实体类属性也添加应该version属性:

package com.example.domain;

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;

@Data
/*@TableName("tbl_user")*/
public class User {
    @TableId(type= IdType.ASSIGN_ID)
    private Long id;
    private String name;
    @TableField(value = "pwd",select = false)
    private String password;
    private Integer age;
    private String tel;
    /*@TableLogic(value = "0",delval = "1")*/
    private Integer deleted;
    @Version
    private Integer version;
    @TableField(exist = false)
    private Integer online;
}

 2、@Version原理🍉

当人人去进行秒杀时,成功抢到商品的用户,会更新用户的version值,

update set_abc=1,version = version + 1 where version=1

如上面这个SQL一样。当一个仅剩的一个商品被抢走,这个version值就会变化,其他人就会显示抢不到商品。

添加乐观锁拦截器(和分页功能一样)🍓

使用这个和分页功能一样,需要添加拦截器:

package com.example.config;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MpConfig {
    @Bean
    public MybatisPlusInterceptor mpInterceptor(){
        //1.定义Mp拦截器
        MybatisPlusInterceptor mpInterceptor = new MybatisPlusInterceptor();
        //2.添加具体的拦截器
        mpInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        //3、添加乐观锁拦截器
        mpInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mpInterceptor;
    }
}

3、测试代码🍓

我们去修改用户id=2的用户名:

 @Test
    void testUpdate(){
        User user=new User();
        user.setId(2L);
        user.setName("编程");
        userDao.updateById(user);
    }

运行发现,version值并没有发生改变:

 这是因为我们没有去添加version值,便无法改变version值。

@Test
    void testUpdate(){
        User user=new User();
        user.setId(2L);
        user.setVersion(1);
        user.setName("编程");
        userDao.updateById(user);
    }

 添加用户的version发现,进行修改操作之后version值+1了:

但是这样手动添加version值很麻烦,我们可以先查询用户信息,然后去进行修改,也是可以的:

@Test
    void testUpdate(){
        //1.先通过要修改的数据id将当前数据查询出来
        User user = userDao.selectById(2L);
        //2.将要修改的属性逐一设置进去
        user.setName("编程1号");
        userDao.updateById(user);
    }

 可以看到version经过用户修改又加了1。

 4、秒杀测试🍓

我们前后修改两次用户名,看最终结果如何:

@Test
    void testUpdate(){
        //1.先通过要修改的数据id将当前数据查询出来
        User user = userDao.selectById(2L);     //version=3

        User user2 = userDao.selectById(2L);    //version=3

        user2.setName("编程 aaa");
        userDao.updateById(user2);              //version=>4
        
        user.setName("编程 bbb");
        userDao.updateById(user);               //verion=3?条件还成立吗?
    }

 可以看到只修改了一次,用户名修改为了 编程 aaa而后面的修改操作未进行:

这和我们上面说的情况是一样的,用户信息进行了修改,version值也会加一,因为你一开始查询到的version值为3,这个时候version已经变成了4,就无法进行修改成为 编程 bbb 了。

二、代码生成器🍭

1、模板🍉

既然是代码生成器,那肯定是有模板的,那我们来看看UserDao,观察看看,哪些是模板里的,哪些是需要更改的。

package com.example.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.domain.User;
import org.apache.ibatis.annotations.Mapper;


@Mapper
public interface UserDao extends BaseMapper<User> {
}

看下面,对于不同的Dao类只需要将下面红框框里的东西替换就行,其他的就是模板。换句话说我们只要将下面红框框里面的东西替换,又是一个新的Dao类。

不仅仅是Dao类实体类也可以提取出模板。

2、代码生成器🍉

模板:MyBatisPlus提供

数据库相关配置:读取数据库获取信息

开发者自定义配置:手工配置

Ⅰ、配置🍓

我们新建一个SpringBoot项目:

pom.xml:其中有所需要的代码生成器velocity模板引擎以及其他需要的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.14</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>mybatis-plus</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>mybatis-plus</name>
    <description>mybatis-plus</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!-- spring webmvc -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- mybatisplus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.1</version>
        </dependency>
        <!-- druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>
        <!-- mysql -->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- 代码生成器 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.4.1</version>
        </dependency>
        <!-- velocity模板引擎 -->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.3</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

Generator类:添加数据库配置

package com.example;

import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;

public class Generator {
    public static void main(String[] args) {
        AutoGenerator autoGenerator=new AutoGenerator();

        DataSourceConfig dataSource=new DataSourceConfig();
        dataSource.setDriverName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/ku2022?characterEncoding=utf8");
        dataSource.setUsername("root");
        dataSource.setPassword("123456");
        autoGenerator.setDataSource(dataSource);

        autoGenerator.execute();
    }
}

运行之后会给我打开一个文件夹:

 可以发现多了一个com文件夹,我们打开里面的controller文件夹,可以发现它给这个库里面每一个表都生成了一个.java文件,这个就是给我们生成的代码:

但是这个东西生成的是不正确的,所以我们将这个文件夹删除掉。

Ⅱ、正确生成代码 🍓

我们应该添加其他配置,让他生成在正确的位置:

package com.example;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;

public class CodeGenerator {
    public static void main(String[] args) {
        //1.获取代码生成器的对象
        AutoGenerator autoGenerator = new AutoGenerator();

        //设置数据库相关配置
        DataSourceConfig dataSource = new DataSourceConfig();
        dataSource.setDriverName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/ku2022?serverTimezone=UTC");
        dataSource.setUsername("root");
        dataSource.setPassword("123456");
        autoGenerator.setDataSource(dataSource);

        //设置全局配置
        GlobalConfig globalConfig = new GlobalConfig();
        //输出的位置
        globalConfig.setOutputDir(System.getProperty("user.dir")+"/src/main/java");    //设置代码生成位置
        globalConfig.setOpen(false);    //设置生成完毕后是否打开生成代码所在的目录
        globalConfig.setAuthor("热爱编程的林兮");    //设置作者
        globalConfig.setFileOverride(true);     //设置是否覆盖原始生成的文件
        globalConfig.setMapperName("%sDao");    //设置数据层接口名,%s为占位符,指代模块名称
        globalConfig.setIdType(IdType.ASSIGN_ID);   //设置Id生成策略
        autoGenerator.setGlobalConfig(globalConfig);

        //2.执行生成操作
        autoGenerator.execute();
    }
}

我们看到上面,点开GlobalConfig源码:

 默认生成代码在D盘。

Ⅲ、生成的代码1🍓

我们运行代码:

可以看到在Java目录下的con文件夹生成了一个baomidou文件夹。

我们打开entity实体类:

可以看到作者就是上面配置文件中设置的作者:热爱编程的林兮 

我们在生成的代码进行修改,然后重新运行 代码生成器。

我们运行发现,它又变回去了,这是因为代码进行了覆盖 

 是下面这段代码带来的影响:

globalConfig.setFileOverride(true);     //设置是否覆盖原始生成的文件

重新运行代码,就会将代码全部重新覆盖。

Ⅳ、生成的代码2🍓

我们继续在CodeGenerator添加新配置:

//设置包名相关配置
        PackageConfig packageInfo = new PackageConfig();
        packageInfo.setParent("com.aaa");   //设置生成的包名,与代码所在位置不冲突,二者叠加组成完整路径
        packageInfo.setEntity("domain");    //设置实体类包名
        packageInfo.setMapper("dao");   //设置数据层包名
        autoGenerator.setPackageInfo(packageInfo);

我们把之前的代码(baomidou)删除掉,重新运行代码。

可以发现重新生成了一个名字为aaa文件夹,不再是原来的名字了。还有实体类的包名也修改了,变成了domin,数据层包名也变成了dao。

Ⅴ、生成的代码3 🍓

//策略设置
        StrategyConfig strategyConfig = new StrategyConfig();
        strategyConfig.setInclude("tbl_user");  //设置当前参与生成的表名,参数为可变参数
        strategyConfig.setTablePrefix("tbl_");  //设置数据库表的前缀名称,模块名 = 数据库表名 - 前缀名  例如: User = tbl_user - tbl_
        strategyConfig.setRestControllerStyle(true);    //设置是否启用Rest风格
        strategyConfig.setVersionFieldName("version");  //设置乐观锁字段名
        strategyConfig.setLogicDeleteFieldName("deleted");  //设置逻辑删除字段名
        strategyConfig.setEntityLombokModel(true);  //设置是否启用lombok
        autoGenerator.setStrategy(strategyConfig);

之前库里面有五个表,这次通过上面代码我只生成了tbl_user表的代码(只想生成我指定表的代码),而且表的实体类加了@Data注解(启用了lombok),设置了乐观锁字段名还有逻辑删除字段名,以及删除了数据表的tbl_前缀。

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

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

相关文章

002-第一代硬件系统架构确立及产品选型

第一代硬件系统架构确立及产品选型 文章目录 第一代硬件系统架构确立及产品选型项目介绍摘要硬件架构硬件结构选型及设计单片机选型上位机选型扯点别的 关键字&#xff1a; Qt、 Qml、 信号采集机、 数据处理、 上位机 项目介绍 欢迎来到我们的 QML & C 项目&#xff…

Centos8下载安装JDK8

安装JDK8 一、下载 官网&#xff1a;https://www.oracle.com/java/technologies/downloads/#java8-linux 二、存放到opt目录下 三、解压 tar -zxvf jdk-8u361-linux-x64.tar.gz -C /usr/local如果下载的是tar格式&#xff0c;则安装如下命令解压 tar -zvf jdk-8u361-linu…

Flash的学习

Flash的学习 1 概述 2 特性 STM32 的内部FLASH 包含主存储器、系统存储器以及选项字节区域。 2.1 主存储器 主存储器分为256 页&#xff0c;每页大小为2KB&#xff0c;共512KB。这个分页的概念&#xff0c;实质就是FLASH 存储器 的扇区&#xff0c;与其它FLASH 一样&…

【C++】动态内存管理(79分钟写的文章哪里看不懂了,快来学)

动态内存管理目录&#xff1a; 一、C/C内存分布 在学习了C/C内存区域的划分后&#xff0c;我们来做几道题巩固一下&#xff1a; 1. 选择题&#xff1a;选项 : A.栈 B.堆 C.数据段(静态区) D.代码段(常量区)globalVar在哪里&#xff1f;____ staticGlobalVar在哪里&#x…

【2023知乎评论爬虫】我用Python爬虫爬了2386条知乎评论!

文章目录 一、爬取目标二、展示爬取结果三、爬虫代码讲解3.1 分析知乎页面3.2 爬虫代码 四、同步视频五、完整源码 您好&#xff0c;我是 马哥python说&#xff0c;一枚10年程序猿。 一、爬取目标 前些天我分享过一篇微博的爬虫&#xff1a;https://blog.csdn.net/solo_msk/a…

Spring 的注入

目录 一、注入&#xff08;Injection&#xff09; 1、什么是注入 &#xff08;1&#xff09;为什么需要注入 &#xff08;2&#xff09;如何进行注入 2、Spring 注入原理分析&#xff08;简易版&#xff09; 二、Set 注入详解 1、JDK 内置类型 &#xff08;1&#xff09…

【修复版】2023新版塔罗 算八字测运易理风水 取名 源码平台 搭建教程

全线修复&#xff0c;欢迎你拿其他家的来比&#xff0c;叫他们发测试连接去测试对比&#xff0c;眼睛骗不了人 很多说自家的是修复版&#xff0c;能像我这样把修复的列出来嘛&#xff0c;顾客朋友也可以直接去问他&#xff1a;你到底修复了个啥&#xff1f;&#xff1f;&#…

深入探索智能问答:从检索到生成的技术之旅

目录 一、智能问答概述1. **语义理解**2. **知识库和数据库**3. **上下文感知**4. **动态学习和自适应** 二、发展历程1. **基于规则的系统**2. **统计方法的兴起**3. **深度学习和神经网络的突破**4. **预训练模型** 三、智能问答系统的主要类型四、基于知识库的问答系统五、基…

如何使用记事本制作一个简陋的小网页(1)

1、创建一个记事本 2、将记事本的尾缀进行修改&#xff0c;变为html html本质上是一种标签并不是一种语言&#xff0c;其最主要的功能就是对页面设置和页面的文本样式进行修改和修缮。 3、右键被修改了尾缀的文本&#xff0c;选择使用记事本的打开方式。 打开完毕后&#xf…

什么是JavaScript的事件驱动编程(event-driven programming)?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 事件&#xff08;Event&#xff09;⭐ 事件监听器&#xff08;Event Listener&#xff09;⭐ 回调函数&#xff08;Callback Function&#xff09;⭐ 非阻塞和异步⭐ 事件循环&#xff08;Event Loop&#xff09;⭐ 触发事件&#xff08;…

「C++程序设计 (面向对象进阶)」学习笔记・二

0、引言 本专栏的系列文章是在学习 北京邮电大学 崔毅东 老师的《C程序设计 (面向对象进阶)》课程过程中整理的。欢迎前往专栏了解更多相关内容~ &#x1f600; 有关于现代 C 的基本介绍&#xff0c;请前往《现代C基本介绍》&#xff01; &#x1f514; 先决条件 本专栏的系列…

【测试开发】答疑篇 · 什么是软件测试

【测试开发】答疑篇 文章目录 【测试开发】答疑篇1. 生活中的测试2. 什么是软件测试3. 为什么要有测试/没有测试行不行4. 软件测试和软件开发的区别5. 软件测试和软件调试之间的区别6. 软件测试的岗位7. 优秀测试人员具备的素质 【测试开发】答疑篇 软件不一定是桌面应用&#…

公众号迁移线上公证如何办?

公众号账号迁移的作用是什么&#xff1f;只能变更主体吗&#xff1f;微信公众平台的帐号迁移功能可将原公众号的粉丝、文章素材、违规记录、留言功能、名称等迁移至新的公众号。通过迁移可以实现公众号的公司主体变更、粉丝转移、开通留言功能、服务号转为订阅号等作用。因此不…

Qt基于paintEvent自定义CharView

Qt基于paintEvent自定义CharView 鼠标拖动&#xff0c;缩放&#xff0c;区域缩放&#xff0c; 针对x轴&#xff0c;直接上代码 charview.h #ifndef CHARVIEW_H #define CHARVIEW_H#include <QWidget> #include <QPainter> #include <QPaintEvent> #inclu…

Kotlin使用infix关键字构建高可读性代码

自从Google推出Kotlin作为官方开发语言后&#xff0c;一堆像我这样的习惯Java开发的程序员从不习惯到爱上这门语言只用了很短的时间&#xff0c;相比于Java语言&#xff0c;kotlin集各家所长&#xff0c;可以使用更少的代码&#xff0c;实现更多更复杂的需求&#xff0c;而且可…

腾讯mini项目-【指标监控服务重构】2023-08-18

今日已办 watermill 将 key 设置到 message 中 修改 watermill-kafka 源码 将 key 设置到 message.metadata中 接入 otel-sdk 添加 middleware resolveUpstreamCtx 解析上游上下文&#xff0c;开启根Span添加 middleware middleware.InstantAck - 马上ACK&#xff0c;使得多…

怒刷LeetCode的第4天(Java版)

#【中秋征文】程序人生&#xff0c;中秋共享# 目录 第一题 题目来源 题目内容 解决方法 方法一&#xff1a;遍历字符串 方法二&#xff1a;有限状态机&#xff08;Finite State Machine&#xff09; 方法三&#xff1a;正则表达式 第二题 题目来源 题目内容 解决方…

机器学习——决策树/随机森林

0、前言&#xff1a; 决策树可以做分类也可以做回归&#xff0c;决策树容易过拟合决策树算法的基本原理是依据信息学熵的概念设计的&#xff08;Logistic回归和贝叶斯是基于概率论&#xff09;&#xff0c;熵最早起源于物理学&#xff0c;在信息学当中表示不确定性的度量&…

带你了解前后端分离的秘密-Vue【vue入门】

&#x1f3c5;我是默&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;在这里&#xff0c;我要推荐给大家我的专栏《Vue》。&#x1f3af;&#x1f3af; &#x1f680;无论你是编程小白&#xff0c;还是有一定基础的程序员&#xff0c;这个专栏…

js中事件委托和事件绑定之间的区别

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 事件绑定&#xff08;Event Binding&#xff09;⭐事件委托&#xff08;Event Delegation&#xff09;⭐ 选择事件绑定或事件委托⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本…