• MyBatis-PLUS使用教程


    引言

    这是一篇mybatis-plus的使用记录博客,源码等分析就不做了,帮助学习mybatis-plus的人懂得使用技巧

    在此之前我转载一篇文章让大家顺带学习一下题外知识,逼格拉满,规范开发,职场上的加分点, 懒得写我就直接丢传送门了, 领域模型
    这里还有什么 失血模型 贫血模型 充血模型 胀血模型我就不说了,我也不太会哈哈哈哈

    MyBatis-PLUS

    介绍

    官方骚话
    愿景
    我们的愿景是成为 MyBatis 最好的搭档,就像 魂斗罗 中的 1P、2P,基友搭配,效率翻倍。

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

    • 官网:https://baomidou.com

    • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑

    • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作

    • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求

    • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错

    • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题

    • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作

    • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )

    • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用

    • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询

    • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库

    • 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询

    • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

    任何能使用 MyBatis 进行 CRUD, 并且支持标准 SQL 的数据库,具体支持情况如下,如果不在下列表查看分页部分教程 PR 您的支持。

    • MySQL,Oracle,DB2,H2,HSQL,SQLite,PostgreSQL,SQLServer,Phoenix,Gauss ,ClickHouse,Sybase,OceanBase,Firebird,Cubrid,Goldilocks,csiidb

    • 达梦数据库,虚谷数据库,人大金仓数据库,南大通用(华库)数据库,南大通用数据库,神通数据库,瀚高数据库

    框架结构

    开始使用

    引入依赖

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0+ 版本</version>
        <relativePath/>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>最新版本</version>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
    </dependencies>
    
    • 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

    在 application.yml 配置文件中添加数据库的相关配置:

    spring:
      datasource:
        url: jdbc:mysql://localhost:3306/databasName?allowMultiQueries=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true
        username: xxx
        password: xxx
        driver-class-name: com.mysql.cj.jdbc.Driver
        type: com.zaxxer.hikari.HikariDataSource
        hikari:
          minimum-idle: 0
          maximum-pool-size: 20
          idle-timeout: 10000
          auto-commit: true
          connection-test-query: select 1
    # 显示SQL语句
    mybatis-plus:
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    配置mybatis-plus配置类,我就直接贴出来了:

    
    /**
     * @author LGH
     */
    @Configuration
    @MapperScan({"com.**.**.**.dao"})
    public class MybatisPlusConfig implements Condition {
    
        private RedisTemplate redisTemplate;
    
        /**
         * 分页插件
         * @return PaginationInterceptor
         */
        @Bean
        @ConditionalOnMissingBean
        public PaginationInterceptor paginationInterceptor() {
            Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent("", "");
            return new PaginationInterceptor();
        }
        /**
         * 逻辑删除插件
         *
         * @return LogicSqlInjector
         */
        @Bean
        @ConditionalOnMissingBean
        public ISqlInjector sqlInjector() {
            return new DefaultSqlInjector();
        }
    
        /**
         * 乐观锁插件
         * @return
         */
        @Bean
        public OptimisticLockerInterceptor optimisticLockerInterceptor() {
            return new OptimisticLockerInterceptor();
        }
    
        @Bean
        @Conditional(MybatisPlusConfig.class)
        public RedisTemplate getRedisTemplate(){
            return new RedisTemplate();
        }
    
        @Override
        public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
            return true;
        }
    }
    
    • 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

    实体类(领域模型):

    @Data
    @TableName("order")
    public class OrderPO extends BasePO {
    // 一般都会有一个BasePO里面记录固定规范属性,id,createTime等和实现Serializable接口
    // BasePO也可以存在copy作用的方法,便于领域模型对象之间的转换
        /**
         * 创建时间
         */
        @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") // 日期格式化
        private Date createTime;
    
        /**
         * 店铺名称
         */
        @TableField(exist = false) // 申明不属于表的字段(一般不会用到)
        private String shopName;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    使用规范

    service:继承IService接口
    mapper:继承BaseMapper接口

    查询方式

    创建查询条件

    条件创建对象的方式
    推荐使用逼格高的流式方式创建

    Wrappers.lambdaQuery().eq() …

    查询:

    LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();

    services:

    this.list(wrapper);
    this.getById(wrapper);
    this.getOne(wrapper);

    controller调用service对象, 同理自己带入就可以了
    xxxService.list(wrapper);

    更新:

    LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>();

    方法同上

    太简单不想写了

    CRUD操作表格

    功能自定义接口MP接口
    新增boole save(T t)int inster(T t)
    删除boole delete(int d)int deleteById(Serializable id
    修改boole update(T t)int updatedById(T t)
    根据id查询T getById(int id)T selectById(Serializable id)
    查询全部List getAll()List<> selectList()
    分页查询PageInfo getAll(int page, int sizeIPage selectPage(IPage page)
    按照条件查询List getAll(Condition condition)IPage selectPage(Wrapper queryWrapper)

    重点说一下分页查询

    IPage<OrderPO> page = new Page<>(area.getCurrent() - 1,10);
    orderService.page(page, new LambdaQueryWrapper<OrderPO>());
    // 参数1是page对象,参数2是我们的条件wrapper对象
    
    • 1
    • 2
    • 3

    干货来了,核心教学

    具体使用中我们会遇到很多场景,会让我们各种复杂语句的查询变得无从下手,举例几个我熟悉的复杂查询,剩下的让你们自己举一反三

    <=,>=

    <=

    Children ge(boolean condition, R column, Object val)
    
    • 1

    >=

    Children le(boolean condition, R column, Object val);
    
    • 1

    and (xxx = xx or xxx = xx)

    有点子长

    Wrappers.<Order>lambdaQuery().and(StringUtils.isNotEmpty(orderDTO.getProdName()), 
    Wrappers.<OrderPO>lambdaQuery()
    .eq(OrderPO::getProdName, orderDTO.getProdName())
    .or().eq(OrderPO::getKeyword, orderDTO.getKeyword()))
    
    • 1
    • 2
    • 3
    • 4

    连表查询动态条件

    @Select("select * from 
        		order o 
                inner join order_sub s in o.id = s.order_id 
                ${qw.customSqlSegment}")
    OrderPO getXxxx(@Param("qw") QueryWrapper wrapper);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    ${qw.customSqlSegment}
    很重点, 这就是你wrapper对象创建后拼接的where和后面的条件部分,可以满足代码优美又能够动态条件的大sql使用场景,基本告别xml

    结束吧,感觉太简单了懒得细聊,坚持写完就不错了

  • 相关阅读:
    RabbitMQ发布确认高级
    [C++]打开新世界的大门之C++入门
    归并排序(递归机制的学习)
    Codeforces Round #620 (Div. 2)ABC
    从GPT入门,到R语言基础与作图、回归模型分析、混合效应模型、多元统计分析及结构方程模型、Meta分析、随机森林模型及贝叶斯回归分析综合应用等专题及实战案例
    Java数组
    谷粒商城----ES篇
    aarch64 麒麟V10创建nvidia_gpu_expoter服务
    第6章:数据库设计基础知识
    一场由Integer引发的血案
  • 原文地址:https://blog.csdn.net/m0_49093968/article/details/125566825