当前位置: 首页 > news >正文

从BaseMapper到LambdaWrapper:MyBatis-Plus的封神之路

一、MyBatis-Plus简介

1.1、介绍

        MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生,官网地址:https://baomidou.com/

1.2、特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

1.3、支持数据库

       任何能使用 MyBatis 进行增删改查,并且支持标准 SQL 的数据库应该都在 MyBatis-Plus 的支持范围内

1.4、框架结构

二、MyBatis-Plus快速上手

2.1、数据准备

        此处依旧采用前篇我们已有的数据库用户表(创建表的SQL语句见前篇):

2.2、项目配置

        创建springboot项目,添加如图所示的依赖即可:

        maven中根据 spring boot 的版本添加依赖:

        Spring Boot 3:

        <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.5</version></dependency>

        Spring Boot 2:

<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.7</version>
</dependency>

        配置数据库:

# 数据库连接配置datasource:url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=falseusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driver

2.3、创建实体类

        创建实体类UserInfo

@Data
public class UserInfo {private Integer id;private String username;private String password;private Integer age;private Integer gender;private String phone;private Integer deleteFlag;private Date createTime;private Date updateTime;
}

        编写mapper接口类

        进入BaseMapper类查看源码:

public interface BaseMapper<T> extends Mapper<T> {int insert(T entity);int deleteById(Serializable id);int deleteById(T entity);...
}

        该类接收一个泛型参数作为操作对象,因此需要将UserInfo传入BaseMapper<>括号中

        MyBatis-Plus 提供了基础的 BaseMapper 接口,该接口已实现单表 CRUD 操作。我们只需让自定义的 Mapper 继承 BaseMapper,即可直接使用这些基础功能,无需自行实现单表增删改查操作

2.4、单元测试(CRUD)

@SpringBootTest
public class MyBatisplusTests {@Autowiredprivate UserInfoMapper userInfoMapper;@Testvoid testSelectByIds(){List<UserInfo> list=userInfoMapper.selectBatchIds(List.of(10,11,12));list.forEach(System.out::println);}@Testvoid testInsert(){UserInfo userInfo=new UserInfo();userInfo.setId(15);userInfo.setAge(35);userInfo.setPassword("123456");userInfo.setGender(1);userInfo.setUsername("程序员");userInfo.setPhone("10010010011");userInfoMapper.insert(userInfo);}@Testvoid testUpdate(){UserInfo userInfo=new UserInfo();userInfo.setId(13);userInfo.setPhone("20022002200");userInfoMapper.updateById(userInfo);}
}

        运行结果;

三、MyBatis-Plus复杂操作

3.1、主要注解

        UserInfoMapper 继承 BaseMapper 时需指定泛型类型,这里的 UserInfo 就是与数据库表对应的实体类,MyBatis-Plus 会根据该实体类自动推断表结构信息

 默认映射规则如下

  1. 表名:将实体类的驼峰命名转换为下划线命名(如 UserInfo → user_info)
  2. 字段:将属性名的驼峰命名转换为下划线命名(如 deleteFlag → delete_flag)
  3. 主键:默认使用 id 字段

        若实体类与数据库表结构不符合上述默认规则,MyBatis-Plus 提供了多种注解来显式指定映射关系:

3.1.1、@TableName

        那么我们根据上述规则进行修改实体类的名称:UserInfo -> Userinfo ,再次执行查询操作:

        这种情况我们就可以通过@TableName注解来标识实体类对应的表

3.1.2、@TableField

        @TableName注解来标识实体类对应的表,那么@TableField这个注解就是用来标识属性对应的字段名

3.1.3、@TableId

        @TableId注解用来指定属性对应的主键

        当属性名与数据库字段名不一致时,需在@TableId注解中明确指定对应字段名;若两者一致,则直接使用@TableId注解即可

3.2、配置日志

mybatis-plus:configuration: # 配置打印 MyBatis⽇志log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

3.3、条件构造器

        MyBatis-Plus也提供了强大的条件构造器(Wrapper)来支持复杂查询场景。这套Wrapper机制允许开发者通过链式调用方式构建查询条件,既能提升开发效率,又能有效避免SQL注入风险

条件构造器😄MyBatis-Plus提供的主要Wrapper类及其功能包括:

  1. AbstractWrapper:所有Wrapper类的基类,封装了通用的查询条件构建方法
  2. QueryWrapper:专用于查询条件的构造,在AbstractWrapper基础上扩展了select方法用于指定查询字段
  3. UpdateWrapper:用于构建更新操作的条件
  4. LambdaQueryWrapper:基于Lambda表达式的查询构造器,通过实体类属性引用避免字段名硬编码
  5. LambdaUpdateWrapper:基于Lambda表达式的更新构造器,同样避免字段名硬编码问题
3.3.1、QueryWrapper

        QueryWrapper不仅适用于查询语句,还可用于构建修改、删除等操作的查询条件

    @Testvoid testQueryWrapper(){QueryWrapper<Userinfo> queryWrapper=new QueryWrapper<Userinfo>().select("id","username","age","phone").eq("age",18).like("phone","19");List<Userinfo> list=userInfoMapper.selectList(queryWrapper);list.forEach(System.out::println);}

请注意:
        默认情况下,Mybatis-Plus会根据@TableField注解自动生成字段别名。但如果指定了QueryWrapper的 select 属性,查询结果将仅包含属性值而丢失别名,导致结果映射失败

        正常查询:

    @Testvoid testQueryWrapper2(){QueryWrapper<Userinfo> wrapper = new QueryWrapper<>();List<Userinfo> users = userInfoMapper.selectList(wrapper);users.forEach(System.out::println);}


        指定select时:

    @Testvoid testQueryWrapper2(){QueryWrapper<Userinfo> wrapper = new QueryWrapper<>();wrapper.select("create_time"); // 明确指定查询字段List<Userinfo> users = userInfoMapper.selectList(wrapper);users.forEach(System.out::println);}

        查询仅包含 create_time 字段,但返回类型为 UserInfo,导致打印结果中其他属性值均为 null

解决方案:

  1. 手动编写自定义SQL
  2. 确保实体类属性名与数据库列名完全一致
  3. 避免在QueryWrapper中显式指定select 字段
  4. 改用LambdaQueryWrapper进行查询

    @Testvoid testQueryWrapper3(){QueryWrapper<Userinfo> wrapper = new QueryWrapper<Userinfo>().lt("age",16);Userinfo userinfo=new Userinfo();userinfo.setPhone("00000000000");userInfoMapper.update(userinfo,wrapper);}
  • lt - "less than" 的缩写,表示"小于"
  • le - "less than or equal to" 的缩写,表示"小于等于"
  • ge - "greater than or equal to" 的缩写,表示"大于等于"
  • gt - "greater than" 的缩写,表示"大于"
  • eq - "equals" 的缩写,表示"等于"
  • ne - "not equals" 的缩写,表示"不等于"

    @Testvoid testQueryWrapper4(){QueryWrapper<Userinfo> wrapper = new QueryWrapper<Userinfo>().eq("delete_flag",1);userInfoMapper.delete(wrapper);}
3.3.2、UpdateWrapper

        我们可以直接使用 UpdateWrapper 进行更新操作,无需创建实体对象即可直接设置更新字段和条件

基础更新

    @Testvoid testUpdateByUpdateWrapper(){UpdateWrapper<Userinfo> updateWrapper = new UpdateWrapper<Userinfo>().set("delete_flag",0).set("age", 5).in("id", List.of(1,2,3));userInfoMapper.update(updateWrapper);}

基于SQL更新

    @Testvoid testUpdateBySQLUpdateWrapper(){UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<UserInfo>().setSql("age = age+10").in("id", List.of(1,2,3));userInfoMapper.update(updateWrapper);}
3.3.3、LambdaQueryWrapper

        使用QueryWrapperUpdateWrapper 时存在一个明显问题:需要手动编写字段名称字符串。如果数据库字段名称发生变更,由于测试覆盖不足,很容易引发生产事故

        MyBatis-Plus提供了基于Lambda表达式的条件构造器解决方案,通过Lambda表达式引用实体类属性,完美解决了字段名硬编码问题。这种方式不仅提升了代码可读性,也显著增强了代码的可维护性

主要实现类包括:

  • LambdaQueryWrapper
  • LambdaUpdateWrapper

这两个类分别对应传统的QueryWrapperUpdateWrapper 功能

    @Testvoid testQueryWrapper5(){QueryWrapper<Userinfo> queryWrapper=new QueryWrapper<Userinfo>();queryWrapper.lambda().select(Userinfo::getId , Userinfo::getAge,Userinfo::getUsername , Userinfo::getPhone).eq(Userinfo::getAge,18).like(Userinfo::getPhone,"19");List<Userinfo> list=userInfoMapper.selectList(queryWrapper);list.forEach(System.out::println);}

3.3.4、LambdaUpdateWrapper
    @Testvoid testLambdUpdateByUpdateWrapper(){UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<UserInfo>();updateWrapper.lambda().set(UserInfo::getDeleteFlag, 0).set(UserInfo::getAge, 5).in(UserInfo::getUserId, List.of(1,2,3));userInfoMapper.update(updateWrapper);}

        or 方法是 MyBatis-Plus 提供的核心查询构造方法之一,主要用于实现 OR 逻辑查询条件。该方法会改变后续查询条件的连接方式,将默认的 AND 连接转换为 OR 连接

3.4、自定义SQL

        当MyBatis-Plus提供的标准操作无法满足我们的需求时,我们可以利用其提供的自定义SQL功能;通过Wrapper构建查询条件,再配合Mapper编写SQL语句,就能灵活实现各种复杂查询需求

---------------mapper------------------
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {@Select("select id,username,password,age FROM user_info ${ew.customSqlSegment}")List<UserInfo> queryUserByCustom(@Param(Constants.WRAPPER) Wrapper<UserInfo> wrapper);
}
---------------test--------------------
@Test
void testQueryUserByCustom(){QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>().eq("username","admin");userInfoMapper.queryUserByCustom(queryWrapper).forEach(System.out::println);
}

注意事项

  • 参数命名:在自定义 SQL 时,若需传递 Wrapper 对象作为参数,必须使用 ew 作为参数名,或者通过 @Param(Constants.WRAPPER) 注解明确指定该参数为 Wrapper 对象
  • 使用方式:在 SQL 语句中,通过 ${ew.customSqlSegment} 来引用 Wrapper 对象生成的 SQL 片段
  • 功能限制:使用自定义 SQL 时,Wrapper 对象不会基于实体类自动生成 where 子句,需要手动编写完整的 SQL 语句
http://www.lryc.cn/news/612661.html

相关文章:

  • day44 力扣1143.最长公共子序列 力扣1035.不相交的线 力扣53. 最大子序和 力扣392.判断子序列
  • WEB开发-第二十七天(PHP篇)
  • 笔试——Day31
  • Linux(17)——Linux进程信号(下)
  • 【42】【OpenCV C++】 计算图像某一列像素方差 或 某一行像素的方差;
  • uniapp vue3中使用pinia 和 pinia持久化(没有使用ts)
  • SQLite 创建表
  • VUE+SPRINGBOOT从0-1打造前后端-前后台系统-文章列表
  • [失败记录] 使用HBuilderX创建的uniapp vue3项目添加tailwindcss3的完整过程
  • 《深入浅出 Django ORM:设计理念与惰性查询实现详解》
  • Django 表单:深度解析与最佳实践
  • 上门家教 app 用户端系统模块设计
  • 解锁高效开发:AWS 前端 Web 与移动应用解决方案详解
  • 深度解析:打造一个文件、可持续的Python网络爬虫——以澳洲房地产网站为例
  • uni-app vue3 小程序接入 aliyun-rtc-wx-sdk
  • 深拷贝之 structuredClone ()
  • JavaSE---异常的经典面试题
  • SUNO音乐歌曲生成平台的关键字指令
  • 内网穿透原理和部署教程
  • [激光原理与应用-171]:测量仪器 - 能量型 - 激光能量计(单脉冲能量测量)
  • YOLOv8面试知识
  • Spring事务失效场景?
  • 【基础知识】springboot+vue 基础框架搭建(更新中)
  • 下载 | Windows Server 2016最新原版ISO映像!(集成7月更新、标准版、数据中心版、14393.8246)
  • MacOS Docker 安装指南
  • 进程、网络通信方法
  • 在Linux下访问MS SQL Server数据库
  • 机器学习工程化 3.0:从“实验科学”到“持续交付”的 7 个关卡
  • 【2025最新】在 macOS 上构建 Flutter iOS 应用
  • 函数、方法和计算属性