• Mybatis-plus快速入门


    Mybatis-Plus

    jpa tk-mapper mybatis-plus

    1、概述

    1.1、简介

    MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

    1.2、特性

    2、快速体验

    2.1、搭建数据库

    DROP TABLE IF EXISTS `user`;
    
    CREATE TABLE `user`
    (
    	id BIGINT(20) NOT NULL COMMENT '主键ID',
    	`name` VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
    	age INT(11) NULL DEFAULT NULL COMMENT '年龄',
    	email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
    	PRIMARY KEY (id)
    );
    
    INSERT INTO `user` (id, `name`, age, email) VALUES
    (1, 'Jone', 18, 'test1@baomidou.com'),
    (2, 'Jack', 20, 'test2@baomidou.com'),
    (3, 'Tom', 28, 'test3@baomidou.com'),
    (4, 'Sandy', 21, 'test4@baomidou.com'),
    (5, 'Billie', 24, 'test5@baomidou.com');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2.2、创建SpringBoot项目

    • 添加依赖

        <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-webartifactId>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-testartifactId>
                <scope>testscope>
            dependency>
            
            <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
                <version>5.1.47version>
            dependency>
            
            <dependency>
                <groupId>com.baomidougroupId>
                <artifactId>mybatis-plus-boot-starterartifactId>
                <version>3.0.5version>
            dependency>
            <dependency>
                <groupId>org.projectlombokgroupId>
                <artifactId>lombokartifactId>
                <version>1.18.10version>
            dependency>
            <dependency>
                <groupId>com.baomidougroupId>
                <artifactId>mybatis-plus-extensionartifactId>
                <version>3.0.5version>
            dependency>
            
            <dependency>
                <groupId>com.baomidougroupId>
                <artifactId>mybatis-plus-generatorartifactId>
                <version>3.4.1version>
            dependency>
            
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38

      高版本的驱动兼容低版本的数据库,8版本的驱动需要增加时区的配置

    原来

    pojo–dao(mybatis配置文件、Mapper.xml配置文件)–service–controller

    现在

    pojo–dao(只需要继承指定泛型的接口:BansMapper)–service–controller

    代码

    User.java

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
        //数据库主键id自动生成:uuid,自增,雪花算法,redis,zookeeper
        @TableId(type = IdType.ID_WORKER)
        private Long id;
        private String name;
        private Integer age;
        private String email;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    UserMapper.java

    @Mapper
    @Repository
    public interface UserMapper extends BaseMapper<User> {
    }
    
    • 1
    • 2
    • 3
    • 4

    application.yml

    spring:
      datasource:
        username: root
        password: 123456
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://localhost:3306/demo?useUniocde=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT%2B8
    
    
    #开启mybatis-plus控制台日志输出
    mybatis-plus:
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    测试

    @SpringBootTest
    class MybatisPlusTestApplicationTests {
        @Autowired
        private UserMapper userMapper;
    
        @Test
        void contextLoads() {
            //测试Mybatis-Plus环境是否搭建成功
            List<User> userList = userMapper.selectList(null);
            for (User user : userList) {
                System.out.println(user.toString());
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    3、逐步击破

    3.1、插入操作

    主键id

    • 主键生成策略:uuid,自增,雪花算法,redis,zookeeper

    • mybatis-plus所带的主键生成策略:@TableId

      @TableId(type = IdType.ID_WORKER)
      private Long id;
      
      • 1
      • 2
    • 分析

      public enum IdType {
          AUTO(0),//数据库id自增
          NONE(1),//该类型为未设置主键类型
          INPUT(2),//手动输入,该类型可以通过自己注册自动填充插件进行填充  
        	//以下3种类型、只有当插入对象ID 为空,才自动填充
          ID_WORKER(3),//雪花算法
          UUID(4),//uuid
          ID_WORKER_STR(5);//字符串全局唯一id
      
          private int key;
      
          private IdType(int key) {
              this.key = key;
          }
      
          public int getKey() {
              return this.key;
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19

    3.2、修改操作

    动态sql

    @Test
    void testUpdate(){
      User user = new User();
      user.setId(5L);
      user.setName("麻腾飞");
      user.setAge(18);
      int i = userMapper.updateById(user);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    时间自动填充

    • 数据库级别

      在这里插入图片描述

      在这里插入图片描述

      @Test
      void testUpdate(){
        User user = new User();
        user.setId(5L);
        user.setName("飞哥");
        user.setAge(9);
        int i = userMapper.updateById(user);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
    • 注解级别(Mybatis-plus自带注解)

      在这里插入图片描述

      在这里插入图片描述

      //User.java
      @TableField(fill = FieldFill.INSERT)//添加数据时,自动给createTime字段添加当前系统时间
      private Date createTime;
      
      @TableField(fill = FieldFill.INSERT_UPDATE)//添加或修改数据时,自动给editTime字段添加当前系统时间
      private Date editTime;
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      //编写处理器来为注解自定义填充策略
      @Slf4j
      @Component
      public class MyMetaObjectHandler implements MetaObjectHandler {
          @Override
          public void insertFill(MetaObject metaObject) {
              log.info("start fill insert...");
              this.setFieldValByName("createTime",new Date(),metaObject);
              this.setFieldValByName("editTime",new Date(),metaObject);
          }
      
          @Override
          public void updateFill(MetaObject metaObject) {
              this.setFieldValByName("editTime",new Date(),metaObject);
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16

    3.3、乐观锁

    什么是乐观锁、悲观锁?自旋锁尝试多次提交

    • 乐观锁:当要更新一条记录时,希望这条记录没有被别人更新

      • 取出记录时,获取当前version
      • 更新时,带上这个version
      • 执行更新时, set version = newVersion where version = oldVersion
      • 如果version不对,就更新失败

    测试Mybatis-plus乐观锁插件

    • 乐观锁执行成功测试

      //实体类加上@Version注解
      @Version
      private Integer version;
      
      • 1
      • 2
      • 3
      //编写配置类注册乐观锁插件
      @Configuration
      @EnableTransactionManagement
      public class MyConfig {
      
          @Bean
          public OptimisticLockerInterceptor optimisticLockerInterceptor() {
              return new OptimisticLockerInterceptor();
          }
      
          //注册乐观锁插件,3.5.x版本的
      //    @Bean
      //    public MybatisPlusInterceptor mybatisPlusInterceptor() {
      //        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
      //        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
      //        return interceptor;
      //    }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      //测试乐观锁成功
      @Test
      void testOptimisticSuccess(){
        //先根据id获取记录,获取当前的version字段的值
        User user = userMapper.selectById(3L);
        user.setName("飞哥");
        int i = userMapper.updateById(user);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

      在这里插入图片描述

      在这里插入图片描述

    • 乐观锁执行成功测试01

      @Test
      void testOptimisticSuccess(){
        //先根据id获取记录,获取当前的version字段的值
        User user = userMapper.selectById(2L);
        //模拟插队线程
        user.setAge(10);
        userMapper.updateById(user);
      
        user.setName("飞哥");
        userMapper.updateById(user);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11

      总结:使用乐观锁插件更新记录,只需要查询一次记录即可

      在这里插入图片描述

    • 乐观锁执行失败

      //测试乐观锁失败
      @Test
      void testOptimisticError(){
        //先根据id获取记录,获取当前的version字段的值
        User user = userMapper.selectById(1L);
        user.setName("飞哥");
        //模拟插队线程
        User user1 = userMapper.selectById(1L);
        user1.setAge(10);
        userMapper.updateById(user1);
      
        userMapper.updateById(user);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13

      在这里插入图片描述

      在这里插入图片描述

    3.4、查询操作

    //测试常用查询操作
    @Test
    void test01(){
      //查询所有数据
      List<User> userList1 = userMapper.selectList(null);
    
      //根据唯一id查询
      User user1 = userMapper.selectById(1L);
    
      //通过多个id查询多条记录
      List<User> userList2 = userMapper.selectBatchIds(Arrays.asList(1L, 2L, 3L));
    
      //通过Map集合查询记录
      Map<String, Object> map = new HashMap<>();
      map.put("name","Jone");
      List<User> userList3 = userMapper.selectByMap(map);
    
      for (User user : userList3) {
        System.out.println(user.toString());
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    3.5、分页查询

    • 原始的limit

    • 分页插件:pageHelper

    • Mybatis-plus自带的分页插件

      //编写配置类配置分页插件
      @Configuration
      @EnableTransactionManagement
      @MapperScan("com.mtf.mapper")
      public class MyConfig {
          // 旧版
          @Bean
          public PaginationInterceptor paginationInterceptor() {
              PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
              // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
              // paginationInterceptor.setOverflow(false);
              // 设置最大单页限制数量,默认 500 条,-1 不受限制
              // paginationInterceptor.setLimit(500);
              // 开启 count 的 join 优化,只针对部分 left join
      //        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
              return paginationInterceptor;
          }
      
          // 最新版
      //    @Bean
      //    public MybatisPlusInterceptor mybatisPlusInterceptor() {
      //        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
      //        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
      //        return interceptor;
      //    }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      //测试分页插件
      @Test
      void testPage(){
        Page<User> userPage = new Page<>();
        userPage.setCurrent(1);
        userPage.setSize(2);
      
        userMapper.selectPage(userPage, null);
        for (User record : userPage.getRecords()) {
          System.out.println(record.toString());
        }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12

      在这里插入图片描述

    3.6、删除操作

    物理删除

    • 物理删除就是普通的删除操作和之前的查询操作类似,把数据从数据库中移除

    逻辑删除

    • 逻辑删除数据并不是把数据从数据库中移除,而是通过改变变量的值让该行数据失效

      #开启mybatis-plus控制台日志输出
      mybatis-plus:
        configuration:
          log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
      
        global-config:
          db-config:
            logic-delete-value: 0 #逻辑已删除设置为0
            logic-not-delete-value: 1 #逻辑未删除设置为1
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      @Configuration
      @EnableTransactionManagement
      @MapperScan("com.mtf.mapper")
      public class MyConfig {
      
        //注册逻辑删除实例
        @Bean
        public ISqlInjector sqlInjector(){
          return new LogicSqlInjector();
        }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      //删除操作
      @Test
      void testDelete(){
        userMapper.deleteById(5L);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5

      在这里插入图片描述

      在这里插入图片描述

      在这里插入图片描述

    3.7、性能分析插件

    用来检测项目开发过程中存在的慢sql,MP的性能分析插件能够设置sql的执行时间,如果一些sql执行时间超过设定值就会停止运行!

    #设置开发环境
    spring:
    	profiles:
    		active:test
    
    • 1
    • 2
    • 3
    • 4
    @Configuration
    @EnableTransactionManagement
    @MapperScan("com.mtf.mapper")
    public class MyConfig {
        //注册性能分析插件
        @Bean
        @Profile({"dev","test"}) //设置dev 和 test 开发环境开启
        public PerformanceInterceptor performanceInterceptor(){
            PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
            performanceInterceptor.setMaxTime(1);//单位毫秒
            performanceInterceptor.setFormat(true);
            return performanceInterceptor;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    3.8、条件查询器Wrapper

    @SpringBootTest
    public class WrapperTest {
        @Autowired
        private UserMapper userMapper;
    
        // 查询name不为空的用户,并且邮箱不为空的用户,年龄大于等于12
        @Test
        void test01(){
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper.isNotNull("name")
                    .isNotNull("email")
                    .ge("age",12);
            List<User> userList = userMapper.selectList(wrapper);
            for (User user : userList) {
                System.out.println(user.toString());
            }
        }
    
        // 查询名字Jone
        @Test
        void test02(){
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper.eq("name","Jone");
            //返回一个结果调用selectOne,返回多个结果调用selectList
            User user = userMapper.selectOne(wrapper);
            System.out.println(user.toString());
        }
    
        // 查询年龄在 20 ~ 30 岁之间的用户
        @Test
        void test03(){
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper.ge("age",10)
                    .le("age",22);
    
            //wrapper.between("age",10,22);
    
            List<User> userList = userMapper.selectList(wrapper);
            for (User user : userList) {
                System.out.println(user.toString());
            }
        }
        //其他功能参考官方文档
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    3.9、代码自动生成器(AutoGenerator )

    通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。

    package com.mtf;
    
    import com.baomidou.mybatisplus.annotation.FieldFill;
    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;
    import com.baomidou.mybatisplus.generator.config.PackageConfig;
    import com.baomidou.mybatisplus.generator.config.StrategyConfig;
    import com.baomidou.mybatisplus.generator.config.po.TableFill;
    import com.baomidou.mybatisplus.generator.config.rules.DateType;
    import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
    
    import java.util.ArrayList;
    
    /**
     * @BelongsProject: Mybatis_Plus_Test
     * @BelongsPackage: com.mtf
     * @Author: Matengfei
     * @CreateTime: 2022-08-10  20:41
     * @Description: TODO
     * @Version: 1.0
     */
    public class CodeGenerator {
        public static void main(String[] args) {
            // 需要构建一个 代码自动生成器 对象
            AutoGenerator mpg = new AutoGenerator();
    
            //1、全局配置
            GlobalConfig globalConfig = new GlobalConfig();
            //指定代码生成的物理位置
            globalConfig.setOutputDir(System.getProperty("user.dir") + "/src/main/java");
            //设置作者
            globalConfig.setAuthor("Matengfei");
            globalConfig.setOpen(false);
            // 是否覆盖
            globalConfig.setFileOverride(false);
            //去掉Service名称前面的I
            globalConfig.setServiceName("%sService");
            globalConfig.setIdType(IdType.ID_WORKER);
            globalConfig.setDateType(DateType.ONLY_DATE);
            globalConfig.setSwagger2(true);
            mpg.setGlobalConfig(globalConfig);
    
            //2、数据源配置
            DataSourceConfig dataSourceConfig = new DataSourceConfig();
            dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/demo?useUnicode=true&useSSL=false&characterEncoding=utf8");
            dataSourceConfig.setDriverName("com.mysql.jdbc.Driver");
            dataSourceConfig.setUsername("root");
            dataSourceConfig.setPassword("123456");
    
            //3、包的配置
            PackageConfig pc = new PackageConfig();
            //只需要改实体类名字 和包名 还有 数据库配置即可
            pc.setModuleName("blog"); pc.setParent("com.kuang");
            pc.setEntity("entity"); pc.setMapper("mapper");
            pc.setService("service"); pc.setController("controller");
            mpg.setPackageInfo(pc);
    
            //4、策略配置
            StrategyConfig strategy = new StrategyConfig();
            //表名
            strategy.setInclude("blog_tags","course","links","sys_settings","user_record"," user_say");
    
            // 设置要映射的表名
            strategy.setNaming(NamingStrategy.underline_to_camel);
            strategy.setColumnNaming(NamingStrategy.underline_to_camel);
            strategy.setEntityLombokModel(true);
    
            // 自动lombok
            strategy.setLogicDeleteFieldName("deleted");
    
            // 自动填充配置
            TableFill gmtCreate = new TableFill("create_time", FieldFill.INSERT);
            TableFill gmtModified = new TableFill("edit_time", FieldFill.INSERT_UPDATE);
            ArrayList<TableFill> tableFills = new ArrayList<>();
            tableFills.add(gmtCreate); tableFills.add(gmtModified);
            strategy.setTableFillList(tableFills);
    
            // 乐观锁
            strategy.setVersionFieldName("version");
            strategy.setRestControllerStyle(true);
            strategy.setControllerMappingHyphenStyle(true);
    
            // localhost:8080/hello_id_2
            mpg.setStrategy(strategy);
            mpg.execute(); //执行
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89

  • 相关阅读:
    设计模式-单例模式
    JMeter 测试脚本编写技巧
    12.ElasticSearch系列之分布式特性及分布式搜索机制(一)
    业务出海,灵感乍现前要先「把手弄脏」
    Apache HTTPD 多后缀解析漏洞
    使用matlab实现图像信号的色彩空间转换
    amd Ubuntu opencl 安装
    腾讯云双11优惠活动有哪些?详细攻略来了!
    2022深圳工业展,正运动技术邀您一起开启激光加工智能制造!
    14、Python -- 列表推导式(for表达式)与控制循环
  • 原文地址:https://blog.csdn.net/qq_48575500/article/details/126274312