MyBatisPlus快速入门

MyBatisPlus

  • 1、MyBatisPlus简介
    • MyBatisPlus概述
    • 入门案例
  • 2、标准数据层开发
    • MyBatisPlus开启日志
    • 标准CRUD
    • 分页查询
  • 3、DQL编程控制
    • 条件查询
    • null值处理
    • 查询投影
    • 查询条件
    • 字段映射与表名映射
  • 4、DML编程控制
    • id生成策略控制
    • 多数据操作
    • 逻辑删除
    • 乐观锁
  • 5、代码生成器

1、MyBatisPlus简介

MyBatisPlus概述

  • MyBatisPlus(简称MP)是基于MyBatis框架基础上开发的增强型工具,旨在简化开发提高效率
  • MyBatisPlus官网1
  • MyBatisPlus官网2
  • MyBatisPlus特性
    1. 无侵入:只做增强不做改变,不会对现有工程产生影响
    2. 强大的CRUD操作:内置通用Mapper,少量配置即可实现单表CRUD操作
    3. 支持Lambda:编写查询条件无需担心字段写错
    4. 支持主键自动生成
    5. 内置分页插件
    6. ……

入门案例

  • 开发方式:
    • 基于MyBatis使用MyBatisPlus
    • 基于SpringBoot使用MyBatisPlus
    • 基于SpringBoot使用MyBatisPlus
  • SpringBoot整合MyBatis开发过程(复习)
    • 创建SpringBoot工程
    • 勾选配置使用的技术
    • 设置dataSource相关配置属性(JDBC参数)
    • 定义数据层接口映射配置

  • 入门案例
    1. 创建数据库
      CREATE DATABASE `mybatisplus_db`;
      
      USER `mybatisplus_db`;
      
      CREATE TABLE `user`(
      	`id` INT(20) NOT NULL PRIMARY KEY,
      	`name` VARCHAR(30) NOT NULL,
      	`password` VARCHAR(30) NOT NULL,
      	`age` INT(3) NOT NULL,
      	`tel` VARCHAR(30) 
      )ENGINE=INNODB DEFAULT CHARSET=utf8;
      
      
      INSERT INTO `user` (`id`,`name`,`password`,`age`,`tel`) VALUES
      (1,'Tom','tom',15,'1234567'),
      (2,'Jerry','jerry',16,'1234568'),
      (3,'Jcok','123456',18,'123456'),
      (4,'小吴','123456',21,'123456')
      
    2. 创建一个SpringBoot工程
      MyBatisPlus快速入门_第1张图片
    3. 导入MyBatisPlus依赖
      <dependency>
          <groupId>com.baomidou</groupId>
          <artifactId>mybatis-plus-boot-starter</artifactId>
          <version>3.5.3.1</version>
      </dependency>
      
    4. 导入数据库驱动依赖
      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>druid</artifactId>
          <version>1.2.16</version>
      </dependency>
      
    5. 编写数据库配置文件
      MyBatisPlus快速入门_第2张图片
    6. 编写实体类
      package com.mybatisplus_01_quickstart.domain;
      
      public class User {
          private Long id;
          private String name;
          private String password;
          private int age;
          private String tel;
      
          @Override
          public String toString( ) {
              return "User{" +
                      "id=" + id +
                      ", name='" + name + '\'' +
                      ", password='" + password + '\'' +
                      ", tel='" + tel + '\'' +
                      '}';
          }
      
          public int getAge( ) {
              return age;
          }
      
          public void setAge( int age ) {
              this.age = age;
          }
      
          public Long getId( ) {
              return id;
          }
      
          public void setId( Long id ) {
              this.id = id;
          }
      
          public String getName( ) {
              return name;
          }
      
          public void setName( String name ) {
              this.name = name;
          }
      
          public String getPassword( ) {
              return password;
          }
      
          public void setPassword( String password ) {
              this.password = password;
          }
      
          public String getTel( ) {
              return tel;
          }
      
          public void setTel( String tel ) {
              this.tel = tel;
          }
      }
      
    7. 编写接口层
      • 定义数据接口,继承 BaseMapper
      package com.mybatisplus_01_quickstart.dao;
      
      import com.baomidou.mybatisplus.core.mapper.BaseMapper;
      import com.mybatisplus_01_quickstart.domain.User;
      import org.apache.ibatis.annotations.Mapper;
      
      @Mapper
      public interface UserDao extends BaseMapper<User> {
      
      }
      
    8. 测试
      package com.mybatisplus_01_quickstart;
      
      import com.mybatisplus_01_quickstart.dao.UserDao;
      import com.mybatisplus_01_quickstart.domain.User;
      import org.junit.jupiter.api.Test;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.boot.test.context.SpringBootTest;
      
      import java.util.List;
      
      @SpringBootTest
      class Mybatisplus01QuickstartApplicationTests {
      
          @Autowired
          private UserDao userDao;
      
          @Test
          void testGetAll( ) {
              List<User> userList = userDao.selectList(null);
              System.out.println(userList);
          }
      
      }
      
    9. 运行结果
      MyBatisPlus快速入门_第3张图片

2、标准数据层开发

MyBatisPlus开启日志

  • 在配置文件中添加配置(application.yml

    #开启mp的日志(输出到控制台)
    mybatis-plus:
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    

标准CRUD

  • 标准CRUD制作

    功能 自定义接口
    新增 boolean save(T t)
    删除 boolean delete(int id)
    修改 boolean update(T t)
    根据id查询 T getById(int id)
    查询全部 List getAll()
    分页查询 PageInfo getAll(int page, int size)
    按条件查询 List getAll
  • 添加

    @Test
    void testSave(){
        User user = new User();
        user.setName("小吴在敲bug");
        user.setId(123L);
        user.setPassword("123456");
        user.setAge(21);
        user.setTel("2929054638");
        userDao.insert(user);
    }
    
  • 删除

    @Test
    void testDelete(){
        userDao.deleteById(123L);
    }
    
  • 修改:有什么属性修改什么属性,没有就不变

    @Test
    void testUpdate(){
        User user = new User();
        user.setName("小吴在敲bug");
        user.setId(1L);
        userDao.updateById(user);
    }
    
  • @Test
    void testGetById(){
        User user = userDao.selectById(1L);
        System.out.println(user);
    }
    

分页查询

  • mp要实现分页查询需要添加拦截器

    package com.mybatisplus_01_quickstart.config;
    
    import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
    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());
    
            return mpInterceptor;
        }
    }
    
  • MyBatisPlus分页demo

    @Test
    void testGetByPage(){
        IPage page = new Page(1,2);     //参数一:从第几页开始        参数二:每页显示多少数据
        userDao.selectPage(page,null);
        System.out.println("当前页码:"+page.getCurrent());
        System.out.println("每页显示数:"+page.getSize());
        System.out.println("一共多少页:"+page.getPages());
        System.out.println("一共多少条数据:"+page.getTotal());
        System.out.println("数据"+page.getRecords());
    }
    

3、DQL编程控制

条件查询

  • MyBatisPlus将书写复杂的SQL查询条件进行了封装,使用编程的形式完成查询条件的组合

    1. 默认是and

    2. 如果or需要添加

      //查询年龄大于等于16岁,小于65岁的用户
      lqw.lt(User::getAge,50).or().ge(User::getAge,16);
      
  • 方式一:按条件查询

    @Test
    void testGetAll( ) {
        //按条件查询
        QueryWrapper qw = new QueryWrapper();
        qw.lt("age",18);
        List<User> userList = userDao.selectList(qw);
        System.out.println(userList);
    }
    
  • 方式二:lambda格式

    @Test
    void testGetAll( ) {
        //lambda格式按条件查询
        QueryWrapper<User> qw = new QueryWrapper();
        qw.lambda().lt(User::getAge,16);
        List<User> userList = userDao.selectList(qw);
        System.out.println(userList);
    }
    
  • lambda对象格式

    @Test
    void testGetAll( ) {
        //lambda对象格式按条件查询
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.lt(User::getAge,16);
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);
    
    }
    

null值处理

  • 在条件查询中添加null判定
    @Test
    void testGetAll( ) {
        //模拟页面传递过来的查询数据
        UserQuery uq = new UserQuery();
        uq.setAge(10);
        
        //lambda对象格式按条件查询
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        //先判断第一个参数是否为true,如果为true连接当前条件
        lqw.lt(null != uq.getAge2(), User::getAge, uq.getAge2());
        lqw.ge(null != uq.getAge() , User::getAge, uq.getAge());
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);
    
    }
    

查询投影

  • 设置要查询的字段

    1. lambda格式
      LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
      lqw.select(User::getAge,User::getName,User::getAge);
      
    2. 普通格式
      @Test
      void testGetAll( ) {
      
          
          QueryWrapper<User> lqw = new QueryWrapper<>();
          lqw.select("id","name","tel");
          List<User> userList = userDao.selectList(lqw);
          System.out.println(userList);
      
      }
      
  • 统计记录(count(1)):不能使用lambda格式

    @Test
    void testGetAll( ) {
    
    
        QueryWrapper<User> qw = new QueryWrapper<>();
        qw.select("count(1) as count");
        List<Map<String, Object>> userList = userDao.selectMaps(qw);
        System.out.println(userList);
    
    }
    
  • 分组查询:不能使用lambda表达式

    • .groupBy(“分组字段”)
    @Test
    void testGetAll( ) {
        QueryWrapper<User> qw = new QueryWrapper<>();
        qw.select("count(1) as count","tel");
        qw.groupBy("tel");
        List<Map<String, Object>> userList = userDao.selectMaps(qw);
        System.out.println(userList);
    
    }
    

查询条件

  • 范围匹配(>、=、between)

    1. lt:小于
    2. le:小于等于
    3. gt:大于
    4. ge:大于等于
    5. eq:等于
    6. between:第一个参数为起始值,第二个为结束值
    @Test
    void testGetAll( ) {
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        //等同于=
        lqw.eq(User::getName,"Jerry").eq(User::getPassword,"jerry2");
        User loginUser = userDao.selectOne(lqw);
        System.out.println(loginUser);
    }
    
  • 模糊匹配(like)

    • 非全文检索版:like匹配
    @Test
    void testGetAll( ) {
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        //模糊查询like
        lqw.likeRight(User::getName,"J");
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);
    }
    
  • 空判定(null)

  • 包含性匹配(in)

  • 分组(group)

  • 排序(order)

  • ……

  • 官网

字段映射与表名映射

  • 问题一:表字段与编码属性设计不同步
  • 问题二:实体类中添加了数据库中未定义的属性
  • 问题三:采用默认查询开放了更多的字段查看权限
  • 问题四:表名与实体类名开发设计不同步

  • 解决方案:

  • 名称:@TableField
    • 类型:属性注解
    • 位置:模型类属性定义上方
    • 作用:设置当前属性对应的数据库表中的字段
    • 例如:
      public class User {
          @TableField(value = "pwd")
          private String password;
          @TableField(exist = false)
      	private Integer online;
      	@TableField(select=false)
      	private Long id;
      }
      
    • value(默认):设置数据库表字段名称
    • exist 设置属性在数据库表字段是否存在,默认为true。此属性无法与value合并使用
    • select:设置属性是否参与查询,此属性与select()映射不冲突

  • 名称: @TableName
    • 类型:类注解
    • 位置:实体类定义上方
    • 作用:设置当前类对应与数据库表关系
    • 例如:
      @TableName(value = "tbl_user")
      public class User {}
      
    • value:设置数据库表名称

4、DML编程控制

id生成策略控制

  • 不同的表应用不同的id生成策略
    • 日志:自增(1,2,3,4,……)
    • 购物订单:特殊硅脂(FQ23948AK3843)
    • 外卖单:关联地区日期等信息(06 04 2023 34 91)
    • 关系表:可省略id
    • ……

  • 名称:@TableId
    • 类型:属性注解
    • 位置:实体类中用于表示主键的属性上方定义
    • 作用:设置当前类中主键属性的生成
    • 例如:
      public class User {
          @TableId(type = IdType.AUTO)
          private Long id;
      }
      

  • AUTO:使用数控id自增策略控制id生成
  • NOME:不设置id生成策略
  • INPUT:用户手工输入id
  • ASSIGN_ID:雪花算法生成id(可兼容数值型与字符串型
  • ASSIGN_UUID:以UUID生成算法作为id生成策略

  • 全局配置
    • 配置id策略
      mybatis-plus:
        # id生成策略
        global-config:
          db-config:
            id-type: assign_id
      
    • 配置数据库表名前缀
      mybatis-plus:
        global-config:
          db-config:
            # 数据库表名前缀
            table-prefix: tbl_
      

多数据操作

  • 根据删除多个数据

    @Test
    void testDelete( ) {
        List<Long> list = new ArrayList<>();
        list.add(1L);
        list.add(2L);
        userDao.deleteBatchIds(list);
    }
    
  • 根据主键查询多条数据

    @Test
    void testSelect( ) {
        List<Long> list = new ArrayList<>();
        list.add(1L);
        list.add(2L);
        userDao.selectBatchIds(list);
    }
    

逻辑删除

  • 删除操作业务问题:业务数据从数据库中丢弃
  • 逻辑删除:为数据设置是否可用状态字段,删除时设置状态字段为不可用状态,数据保留在数据库中
  • 标记逻辑删除以后使用mp查询不出来

  1. 修改数据库,添加一个字段,并设置默认值
    在这里插入图片描述

  2. 修改实体类

    • value:没有删除的标记
    • delval:删除的标记
    package com.mybatisplus_03_dml.domain;
    
    import com.baomidou.mybatisplus.annotation.IdType;
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableLogic;
    import lombok.Data;
    
    
    
    @Data
    public class User {
        @TableId(type = IdType.AUTO)
        private Long id;
        private String name;
        private String password;
        private Integer age;
        private String tel;
        //逻辑删除字段,标记当前记录是否被删除
        @TableLogic(value = "0",delval = "1")
        private Integer deleted;
    }
    
  3. 测试

    @Test
    void testDelete(){
        userDao.deleteById(3l);
    }
    
  4. 运行结果
    在这里插入图片描述

  5. 逻辑删除全局配置

    mybatis-plus:
      global-config:
        db-config:
          logic-delete-field: deleted   #删除标记字段
          logic-not-delete-value: 0     #显示标记
          logic-delete-value: 1         #删除标记
    

乐观锁

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

  1. 修改数据库:添加字段来标记谁在操作这个数据
    MyBatisPlus快速入门_第4张图片

  2. 修改实体类

    package com.mybatisplus_03_dml.domain;
    
    import com.baomidou.mybatisplus.annotation.IdType;
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableLogic;
    import com.baomidou.mybatisplus.annotation.Version;
    import lombok.Data;
    
    
    
    @Data
    public class User {
        @TableId(type = IdType.AUTO)
        private Long id;
        private String name;
        private String password;
        private Integer age;
        private String tel;
        private Integer deleted;
        @Version			//添加注解
        private Integer version;
    }
    
  3. 编写拦截器

    package com.mybatisplus_03_dml.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 OptimisticLockerInnerInterceptor());
            
            return mpInterceptor;
        }
    }
    
    
  4. 测试

        @Test
        void testUpdate(){
            //1.先查询数据,获取到version数据
            User userA = userDao.selectById(2l);        //version=2
            User userB = userDao.selectById(2l);        //version=2
            //2.执行数据修改操作
            userB.setName("JockAAA");
            userDao.updateById(userB);          //version=3
    
            userA.setName("JockBBB");
            userDao.updateById(userB);          //version=2?条件不成立
        }
    

5、代码生成器

  • 模板:MyBatisPlus提供
  • 数据库相关配置:读取数据库获取信息
  • 开发者自定义配置:手工配置

  1. 创建一个新工程
    MyBatisPlus快速入门_第5张图片

  2. 导入依赖

    <!--MyBatisPlus-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.3.1</version>
    </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>
    
  3. 编写代码生成器

    package com.mybatisplus_04_generator;
    
    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;
    
    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://localhost:3306/mybatisplus_db");
            dataSource.setUsername("root");
            dataSource.setPassword("123456");
            autoGenerator.setDataSource(dataSource);
    
            //设置全局配置
            GlobalConfig globalConfig = new GlobalConfig();
            //设置代码生成位置
            globalConfig.setOutputDir(System.getProperty("user.dir")+"/mybatisplus_04_generator/src/main/java");
            //设置生成完毕是否打开生成代码所在的目录
            globalConfig.setOpen(false);
            //设置作者
            globalConfig.setAuthor("小吴在敲Bug");
            //设置是否覆盖原始生成的文件
            globalConfig.setFileOverride(true);
            //设置数据层接口名,%s为占位符,指代实体类名称
            globalConfig.setMapperName("%sDao");
            //设置id生成策略
            globalConfig.setIdType(IdType.ASSIGN_ID);
            //添加配置
            autoGenerator.setGlobalConfig(globalConfig);
    
            //设置包名相关配置
            PackageConfig packageConfig = new PackageConfig();
            //设置生成的报名,与代码所在位置不冲突,二者叠加完整路径
            packageConfig.setParent("com.mybatisplus_04_generator");
            //设置实体类包名
            packageConfig.setEntity("domain");
            //设置实体类包名
            packageConfig.setMapper("dao");
            //添加配置
            autoGenerator.setPackageInfo(packageConfig);
    
            //策略配置
            StrategyConfig strategyConfig = new StrategyConfig();
            //设置当前参与生成的表名,参数为可变参数
            strategyConfig.setInclude("tbl_user");
            //设置数据库表的前缀名称:实体类名 = 数据库表名 - 前缀名    例如:User=tbl_user
            strategyConfig.setTablePrefix("tbl_");
            //设置是否启用Rest风格
            strategyConfig.setRestControllerStyle(true);
            //设置乐观锁字段名
            strategyConfig.setLogicDeleteFieldName("deleted");
            //设置是否启用Lombok
            strategyConfig.setEntityLombokModel(true);
            //添加配置
            autoGenerator.setStrategy(strategyConfig);
    
    
            //执行代码生成器
            autoGenerator.execute();
        }
    }
    

你可能感兴趣的:(Java笔记,mybatis,java,开发语言)