Mybatis-plus快速入门

发布于:2023-01-22 ⋅ 阅读:(9) ⋅ 点赞:(0) ⋅ 评论:(0)

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');

2.2、创建SpringBoot项目

  • 添加依赖

      <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-test</artifactId>
              <scope>test</scope>
          </dependency>
          <!--mysql数据库驱动-->
          <dependency>
              <groupId>mysql</groupId>
              <artifactId>mysql-connector-java</artifactId>
              <version>5.1.47</version>
          </dependency>
          <!--mybatis-plus-->
          <dependency>
              <groupId>com.baomidou</groupId>
              <artifactId>mybatis-plus-boot-starter</artifactId>
              <version>3.0.5</version>
          </dependency>
          <dependency>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
              <version>1.18.10</version>
          </dependency>
          <dependency>
              <groupId>com.baomidou</groupId>
              <artifactId>mybatis-plus-extension</artifactId>
              <version>3.0.5</version>
          </dependency>
          <!--代码生成器依赖-->
          <dependency>
              <groupId>com.baomidou</groupId>
              <artifactId>mybatis-plus-generator</artifactId>
              <version>3.4.1</version>
          </dependency>
          
    

    高版本的驱动兼容低版本的数据库,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;
}

UserMapper.java

@Mapper
@Repository
public interface UserMapper extends BaseMapper<User> {
}

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

测试

@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());
        }
    }
}

3、逐步击破

3.1、插入操作

主键id

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

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

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

    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;
        }
    }
    

3.2、修改操作

动态sql

@Test
void testUpdate(){
  User user = new User();
  user.setId(5L);
  user.setName("麻腾飞");
  user.setAge(18);
  int i = userMapper.updateById(user);
}

在这里插入图片描述

时间自动填充

  • 数据库级别

    在这里插入图片描述

    在这里插入图片描述

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

    在这里插入图片描述

    在这里插入图片描述

    //User.java
    @TableField(fill = FieldFill.INSERT)//添加数据时,自动给createTime字段添加当前系统时间
    private Date createTime;
    
    @TableField(fill = FieldFill.INSERT_UPDATE)//添加或修改数据时,自动给editTime字段添加当前系统时间
    private Date editTime;
    
    //编写处理器来为注解自定义填充策略
    @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);
        }
    }
    

3.3、乐观锁

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

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

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

测试Mybatis-plus乐观锁插件

  • 乐观锁执行成功测试

    //实体类加上@Version注解
    @Version
    private Integer version;
    
    //编写配置类注册乐观锁插件
    @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;
    //    }
    }
    
    //测试乐观锁成功
    @Test
    void testOptimisticSuccess(){
      //先根据id获取记录,获取当前的version字段的值
      User user = userMapper.selectById(3L);
      user.setName("飞哥");
      int i = userMapper.updateById(user);
    }
    

    在这里插入图片描述

    在这里插入图片描述

  • 乐观锁执行成功测试01

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

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

    在这里插入图片描述

  • 乐观锁执行失败

    //测试乐观锁失败
    @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);
    }
    

    在这里插入图片描述

    在这里插入图片描述

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());
  }
}

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;
    //    }
    }
    
    //测试分页插件
    @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());
      }
    }
    

    在这里插入图片描述

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
    
    @Configuration
    @EnableTransactionManagement
    @MapperScan("com.mtf.mapper")
    public class MyConfig {
    
      //注册逻辑删除实例
      @Bean
      public ISqlInjector sqlInjector(){
        return new LogicSqlInjector();
      }
    }
    
    //删除操作
    @Test
    void testDelete(){
      userMapper.deleteById(5L);
    }
    

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

3.7、性能分析插件

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

#设置开发环境
spring:
	profiles:
		active:test
@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;
    }
}

在这里插入图片描述

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());
        }
    }
    //其他功能参考官方文档
}

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(); //执行
    }
}