• MybatisPlus(5)


    前言🍭

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

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

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

    一、乐观锁(update)🍭

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

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

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

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

    添加version字段,默认值为1

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

    1. package com.example.domain;
    2. import com.baomidou.mybatisplus.annotation.*;
    3. import lombok.Data;
    4. @Data
    5. /*@TableName("tbl_user")*/
    6. public class User {
    7. @TableId(type= IdType.ASSIGN_ID)
    8. private Long id;
    9. private String name;
    10. @TableField(value = "pwd",select = false)
    11. private String password;
    12. private Integer age;
    13. private String tel;
    14. /*@TableLogic(value = "0",delval = "1")*/
    15. private Integer deleted;
    16. @Version
    17. private Integer version;
    18. @TableField(exist = false)
    19. private Integer online;
    20. }

     2、@Version原理🍉

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

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

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

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

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

    1. package com.example.config;
    2. import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
    3. import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
    4. import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
    5. import org.springframework.context.annotation.Bean;
    6. import org.springframework.context.annotation.Configuration;
    7. @Configuration
    8. public class MpConfig {
    9. @Bean
    10. public MybatisPlusInterceptor mpInterceptor(){
    11. //1.定义Mp拦截器
    12. MybatisPlusInterceptor mpInterceptor = new MybatisPlusInterceptor();
    13. //2.添加具体的拦截器
    14. mpInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
    15. //3、添加乐观锁拦截器
    16. mpInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
    17. return mpInterceptor;
    18. }
    19. }

    3、测试代码🍓

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

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

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

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

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

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

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

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

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

     4、秒杀测试🍓

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

    1. @Test
    2. void testUpdate(){
    3. //1.先通过要修改的数据id将当前数据查询出来
    4. User user = userDao.selectById(2L); //version=3
    5. User user2 = userDao.selectById(2L); //version=3
    6. user2.setName("编程 aaa");
    7. userDao.updateById(user2); //version=>4
    8. user.setName("编程 bbb");
    9. userDao.updateById(user); //verion=3?条件还成立吗?
    10. }

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

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

    二、代码生成器🍭

    1、模板🍉

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

    1. package com.example.dao;
    2. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    3. import com.example.domain.User;
    4. import org.apache.ibatis.annotations.Mapper;
    5. @Mapper
    6. public interface UserDao extends BaseMapper {
    7. }

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

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

    2、代码生成器🍉

    模板:MyBatisPlus提供

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

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

    Ⅰ、配置🍓

    我们新建一个SpringBoot项目:

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

    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    4. <modelVersion>4.0.0modelVersion>
    5. <parent>
    6. <groupId>org.springframework.bootgroupId>
    7. <artifactId>spring-boot-starter-parentartifactId>
    8. <version>2.7.14version>
    9. <relativePath/>
    10. parent>
    11. <groupId>com.examplegroupId>
    12. <artifactId>mybatis-plusartifactId>
    13. <version>0.0.1-SNAPSHOTversion>
    14. <name>mybatis-plusname>
    15. <description>mybatis-plusdescription>
    16. <properties>
    17. <java.version>1.8java.version>
    18. properties>
    19. <dependencies>
    20. <dependency>
    21. <groupId>org.springframework.bootgroupId>
    22. <artifactId>spring-boot-starter-webartifactId>
    23. dependency>
    24. <dependency>
    25. <groupId>com.baomidougroupId>
    26. <artifactId>mybatis-plus-boot-starterartifactId>
    27. <version>3.4.1version>
    28. dependency>
    29. <dependency>
    30. <groupId>com.alibabagroupId>
    31. <artifactId>druidartifactId>
    32. <version>1.1.16version>
    33. dependency>
    34. <dependency>
    35. <groupId>com.mysqlgroupId>
    36. <artifactId>mysql-connector-jartifactId>
    37. <scope>runtimescope>
    38. dependency>
    39. <dependency>
    40. <groupId>org.springframework.bootgroupId>
    41. <artifactId>spring-boot-starter-testartifactId>
    42. <scope>testscope>
    43. dependency>
    44. <dependency>
    45. <groupId>org.projectlombokgroupId>
    46. <artifactId>lombokartifactId>
    47. <optional>trueoptional>
    48. dependency>
    49. <dependency>
    50. <groupId>com.baomidougroupId>
    51. <artifactId>mybatis-plus-generatorartifactId>
    52. <version>3.4.1version>
    53. dependency>
    54. <dependency>
    55. <groupId>org.apache.velocitygroupId>
    56. <artifactId>velocity-engine-coreartifactId>
    57. <version>2.3version>
    58. dependency>
    59. dependencies>
    60. <build>
    61. <plugins>
    62. <plugin>
    63. <groupId>org.springframework.bootgroupId>
    64. <artifactId>spring-boot-maven-pluginartifactId>
    65. plugin>
    66. plugins>
    67. build>
    68. project>

    Generator类:添加数据库配置

    1. package com.example;
    2. import com.baomidou.mybatisplus.generator.AutoGenerator;
    3. import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
    4. public class Generator {
    5. public static void main(String[] args) {
    6. AutoGenerator autoGenerator=new AutoGenerator();
    7. DataSourceConfig dataSource=new DataSourceConfig();
    8. dataSource.setDriverName("com.mysql.cj.jdbc.Driver");
    9. dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/ku2022?characterEncoding=utf8");
    10. dataSource.setUsername("root");
    11. dataSource.setPassword("123456");
    12. autoGenerator.setDataSource(dataSource);
    13. autoGenerator.execute();
    14. }
    15. }

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

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

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

    Ⅱ、正确生成代码 🍓

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

    1. package com.example;
    2. import com.baomidou.mybatisplus.annotation.IdType;
    3. import com.baomidou.mybatisplus.generator.AutoGenerator;
    4. import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
    5. import com.baomidou.mybatisplus.generator.config.GlobalConfig;
    6. public class CodeGenerator {
    7. public static void main(String[] args) {
    8. //1.获取代码生成器的对象
    9. AutoGenerator autoGenerator = new AutoGenerator();
    10. //设置数据库相关配置
    11. DataSourceConfig dataSource = new DataSourceConfig();
    12. dataSource.setDriverName("com.mysql.cj.jdbc.Driver");
    13. dataSource.setUrl("jdbc:mysql://localhost:3306/ku2022?serverTimezone=UTC");
    14. dataSource.setUsername("root");
    15. dataSource.setPassword("123456");
    16. autoGenerator.setDataSource(dataSource);
    17. //设置全局配置
    18. GlobalConfig globalConfig = new GlobalConfig();
    19. //输出的位置
    20. globalConfig.setOutputDir(System.getProperty("user.dir")+"/src/main/java"); //设置代码生成位置
    21. globalConfig.setOpen(false); //设置生成完毕后是否打开生成代码所在的目录
    22. globalConfig.setAuthor("热爱编程的林兮"); //设置作者
    23. globalConfig.setFileOverride(true); //设置是否覆盖原始生成的文件
    24. globalConfig.setMapperName("%sDao"); //设置数据层接口名,%s为占位符,指代模块名称
    25. globalConfig.setIdType(IdType.ASSIGN_ID); //设置Id生成策略
    26. autoGenerator.setGlobalConfig(globalConfig);
    27. //2.执行生成操作
    28. autoGenerator.execute();
    29. }
    30. }

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

     默认生成代码在D盘。

    Ⅲ、生成的代码1🍓

    我们运行代码:

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

    我们打开entity实体类:

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

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

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

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

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

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

    Ⅳ、生成的代码2🍓

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

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

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

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

    Ⅴ、生成的代码3 🍓

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

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

  • 相关阅读:
    pytorch深度学习入门
    Nginx
    Oracle数据库经纬度坐标查询优化与结果错误原因分析、SQL中WKT超长文本字符串处理
    8.8本周总结
    leetcode 12. Integer to Roman(整数转罗马数字)
    SpringBoot轻松实现项目集成Knife4j接口文档
    易灵思T35 FPGA驱动LVDS显示屏
    css,sass,scss和less的区别
    30分钟吃掉pytorch中的各种归一化层
    简单易上手,亚马逊云科技Amazon CodeWhisperer个性化辅助功能成为开发者好帮手
  • 原文地址:https://blog.csdn.net/m0_63951142/article/details/132558864