• 【主流技术】Mybatis Plus的理解与应用


    前言

    mybatis plus是一个mybatis的增强工具,在其基础上只做增强不做改变。作为开发中常见的第三方组件,学习并应用在项目中可以节省开发时间,提高开发效率。

    官方文档地址:MyBatis-Plus (baomidou.com)

    一、特性

    1.1损耗小

    自动注入基本CRUD,性能无损耗,直接面向对象操作(通过BaseMaper<约定的泛型>);

    1.2支持lambda表达式

    通过lambda表达式的形式,方便编写各类查询条件,无需担心字段出错;

    1.3支持主键自动生成

    内含分布式唯一ID生成器-Squence,可自行配置主键;

    1.4支持ActiveRecord模式

    实体类只需继承Model类即可进行CRUD操作;

    1.5支持分页插件

    基于mybatis物理分页,配置好插件后自动将数据分页;

    二、快速入门

    2.1创建数据库

    2.1.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)
    );
    
    2.1.2初始化项目
    • 导入依赖(尽量不要与mybatis一起导入)
    • 配置依赖
    • 编写代码
    • 拓展技术能力
            <!--mybatis-plus-->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.3.2</version>
            </dependency>
    
    2.1.3连接数据库
    #mysql配置
    #数据库用户名
    spring.datasource.username=root
    #登录密码
    spring.datasource.password=password123
    #JDBC地址、编码、安全连接
    spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8
    #数据库驱动
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    

    2.2编写代码

    2.2.1实体类
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
        //用户id
        private Long id;
        //用户名
        private String name;
       //年龄
        private Integer age;
       //邮箱
        private String email;
    }
    
    
    2.2.2mapper文件
    @Mapper
    @Repository
    //该接口继承BaseMapper类所有方法
    public interface UserMapper extends BaseMapper<User> {
    }
    
    2.2.3逻辑实现层
        @Autowired
        private UserMapper userMapper;
      //创建条件构造器
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            userMapper.selectList(wrapper);
     
    

    2.3日志配置

    #mybatis-plus日志配置,默认控制台输出日志,properties文件
    mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
    

    2.4CRUD扩展

    2.4.1插入操作(insert)
        void insert(){
            User user = new User();
            user.setName("Alex");
            user.setAge(42);
            user.setEmail("4353435@qq.com");
            //受影响的行数
            int result = userMapper.insert(user);
            System.out.println(result);
            System.out.println(user);
        }
    

    主键生成策略

    实体类声明数据库表名,同时设置主键id为自增。

    //数据库表名
    @TableName("user")
    public class User implements Serializable {
        //用户id,主键自增
        @TableId(value = "id",type = IdType.AUTO)
        private Long id;
    }
    
    2.4.2更新操作(update)
     //更新操作
        @Test
        void updateTest(){
            User user = new User();
            user.setId(3L);
            user.setName("docker&K8s");
            //操作结果条数
            int i = userMapper.updateById(user);
            System.out.println(i);
        }
    
    时间自动填充策略
    方式一(数据库级别):不推荐使用

    在数据库中新建字段并设置为操作的当前时间,且需要在实体类同步属性:

    从而达到自动填充时间的。

     private Date createTime;
     private Date updateTime;
    
    方式二(代码级别):
    • 在实体类属性加上对应注解,自动填充时间字段:
        @TableField(fill = FieldFill.INSERT)
        private Date createTime;
    
        @TableField(fill = FieldFill.UPDATE)
        private Date updateTime;
    
    • 代码逻辑中新建时间对象获取当前时间(推荐使用):
    user.setUpdateTime(new Date());
    
    2.4.3乐观锁处理

    在面试中经常会提及悲观锁、乐观锁的概念,其实这两个概念非常简单。

    乐观锁

    乐观锁顾名思义十分乐观,它总是认为不会出现问题,无论干什么都不会去上锁。如果出现问题,就再更新值去测试。

    悲观锁

    悲观锁顾名思义十分悲观,它总是认为会出现问题,无论干什么都会去上锁,然后再去操作。

    乐观锁机制

    • 取出记录时,获取当前version
    • 更新时带上该version
    • 执行更新时,set version = newVersion where version = oldVersion
    • 若version不对,则更新失败
    乐观锁:1、先去查询获得版本号version = 1
    --A线程
    update user set name = "zhuzhiqiang",version = version + 1
    where id = 2 and version = 1
    
    若B线程抢先完成,这时version = 2,导致线程A修改失败
    --B线程
    update user set name = "zhuzhiqiang",version = version + 1
    where id = 2 and version = 1
    

    测试mybatisPlus的乐观锁插件

    1、在数据库表中添加version字段:

    2、实体类添加对应属性,并添加@Version注解:

      //乐观锁字段(注解)
      @Version
      private Integer version;
    

    3、注册组件:

    @EnableTransactionManagement //事务管理注解
    @Configuration
    public class MyBatisPlusConfig { 
        //注册乐观锁插件
        @Bean
        public OptimisticLockerInterceptor optimisticLockerInterceptor(){
            return new OptimisticLockerInterceptor();
        }
    }
    
    2.4.4分页查询处理(本质上还是执行limit)

    使用步骤

    1. 配置拦截器组件(配置类中):

      //分页查询插件
          @Bean
          public PaginationInterceptor paginationInterceptor(){
             return new PaginationInterceptor();
          }
      
    2. 直接使用Page对象即可:

       //测试分页查询
          @Test
          public void testPage(){
              //page对象 参数1:当前页;参数2:页面展示条数
              Page<User> page = new Page<>(1,5);
              userMapper.selectPage(page,null);
              page.getRecords().forEach(System.out::println);
          }
      
    2.4.5删除操作

    逻辑删除

    逻辑删除指的是在数据库中没有被删除,而是通过一个变量来使其失效:deleted = 0 -> deleted = 1

    1. 数据库表中增加字段:

    2. 实体类中添加对应属性:

        //逻辑删除(注解) 
        @TableLogic
        private Integer deleted;
      
    3. properties配置:

      #mybatis-plus逻辑删除配置,删除为1,未删除为0
      mybatis-plus.global-config.db-config.logic-delete-value = 1
      mybatis-plus.global-config.db-config.logic-not-delete-value = 0
      
    4. 测试删除(本质上是一个更新操作):

      注:若执行了逻辑删除,那么再次查询该条数据时,会在select语句中自动拼接deleted=0,即查询不到该条语句。

    2.4.6条件构造器Wrapper

    按照复杂条件进行查询,本质上等价于使用复杂sql进行查询。

    1. 源码分析:

      //wrapper是条件构造器对象,底层继承Wrapper类走SQL查询
      QueryWrapper<User> wrapper = new QueryWrapper<>();
      
    2. 测试使用:

          public void testWrapper(){
              String WxUserId = "16";
              QueryWrapper<User> wrapper = new QueryWrapper<>();
              //相当于where语句,查询一条wx_user_id字段中值为WxUserId,且opinion_id字段中值为opinionId的信息
              wrapper
                    .eq("wx_user_id",WxUserId)
                    .eq("opinion_id", opinionId);
              userMapper.selectOne(wrapper);
          }
      
    3. 复杂条件的SQL查询

      • like模糊查询

         public void testLike(){
                QueryWrapper<User> wrapper = new QueryWrapper<>();
                //相当于where语句,
                wrapper
                      //表示name字段中 不包含e的数据
                      .notLike("name","e")
                      //右查询,以t开头的email字段数据
                      .likeRight("email", "t");
            }
        

    三、高级用法

    3.1基本概念

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

    3.2创建工具类

    public class AutoCodeTool {
        public static void main(String[] args) {
            //构建代码自动生成器对象
            AutoGenerator autoCode = new AutoGenerator();
            //全局配置生效
            autoCode.setGlobalConfig(gc);
            //数据源生效
            autoCode.setDataSource(dsc);
            //包配置生效
            autoCode.setPackageInfo(packageConfig);
            //其它策略生效
            autoCode.setStrategy(strategyConfig);
            //执行代码生成器
            autoCode.execute();
        }
    }
    

    3.3全局配置

    //1、全局配置
    GlobalConfig gc = new GlobalConfig();
    //输出目录,将自动生成的代码生成在以下路径中
    String projectPath = System.getProperty("user.dir");
    gc.setOutputDir(projectPath + "/src/main/java");
    //设置作者信息
    gc.setAuthor("Created by zhuzqc");
    //生成代码后不打开文件管理器
    gc.setOpen(false);
    //是否覆盖原来生成的代码
    gc.setFileOverride(false);
    //主键类型
    gc.setIdType(IdType.ID_WORKER);
    //时间类型
    gc.setDateType(DateType.ONLY_DATE);
    //配置swagger文档
    gc.setSwagger2(true);
    

    3.4设置数据源

    //2、设置数据源
    DataSourceConfig dsc = new DataSourceConfig();
    //数据源具体配置
    dsc.setUrl("jdbc:mysql://localhost:3306/mubatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8");
    dsc.setDriverName("com.mysql.cj.jdbc.Driver");
    dsc.setUsername("root");
    dsc.setPassword("password123");
    dsc.setDbType(DbType.MYSQL);
    

    3.5包的配置

    //3、包的配置
    PackageConfig packageConfig = new PackageConfig();
    //生成包路径
    packageConfig.setParent("com.dcone");
    //生成模块名
    packageConfig.setModuleName("common");
    //生成entity
    packageConfig.setEntity("pojo");
    //生成mapper
    packageConfig.setMapper("dao");
    //生成service
    packageConfig.setService("service");
    //生成controller
    packageConfig.setController("controller");
    

    3.6其它策略

    //4、其它策略
    StrategyConfig strategyConfig = new StrategyConfig();
    //设置需要映射的数据库表
    strategyConfig.setInclude("user");
    //驼峰命名
    strategyConfig.setNaming(NamingStrategy.underline_to_camel);
    strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);
    //设置Lombok
    strategyConfig.setEntityLombokModel(true);
    //RESTFUL风格
    strategyConfig.setRestControllerStyle(true);
    //逻辑删除
    strategyConfig.setLogicDeleteFieldName("deleted");
    //自动填充配置(创建和修改时间)
    TableFill gmtCreate = new TableFill("gmt_create_time", FieldFill.INSERT);
    TableFill gmtModified = new TableFill("gmt_modified_time", FieldFill.INSERT_UPDATE);
    autoCode.setStrategy(strategyConfig);
    //作为列表元素添加自动填充策略
    ArrayList<TableFill> tableFills = new ArrayList<>();
    tableFills.add(gmtCreate);
    tableFills.add(gmtModified);
    strategyConfig.setTableFillList(tableFills);
    //乐观锁配置
    strategyConfig.setVersionFieldName("version");
    //访问URL下划线风格
    strategyConfig.setControllerMappingHyphenStyle(true);
    

    四、总结

    4.1优点

    • 通过少量配置即可实现单表大部分 CRUD 操作(将简单查询封装),更有强大的条件构造器,满足各类使用需求;
    • 采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎;
    • 支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作。

    4.2缺点

    • 对数据访问层DAO的上层入侵太强,入侵到service、甚至controller,将层次结构耦合起来;
    • 数据查询代码复杂,最终SQL过程黑盒,不利于业务性优化,不利于排查问题;
    • 一旦项目跃迁到微服务,其难以在复杂高性能大规模服务上应用。
  • 相关阅读:
    uniapp主题切换功能的第二种实现方式(scss变量+require)
    vscode 画流程图
    [管理与领导-116]:IT人看清职场中的隐性规则 - 13 - 项目负责人如何帮助项目经理提升项目管理的威望、成就感、积极性,从而提升项目执行的效率?
    Python爬虫如何解决提交参数js加密
    小程序+自定义插件的混合模式
    Django(ORM事务操作|ORM常见字段类型|ORM常见字段参数|关系字段|Meta元信息)
    5、nerf++(pytorch)
    Java代理模式
    泛型+IO流基础知识+java->符号 lambda表达式
    删除线上无用redis数据的方案(telnet+scan+python脚本)
  • 原文地址:https://www.cnblogs.com/Apluemxa/p/16369730.html