前一篇文章中,小编介绍到了Mybatis,以及它的增强工具,mybatis-generator。
那么为了再减少对于SQL语句的编写,那么mybatis的另一个增强工具也是做出了巨大努力。
Mybaits-Plus
Mybatis-Plus简称MP,它是一个Mybatis的增强工具之一,在Mybatis的基础上只做增强不做改变,为简化开发而生
,提高效率而生。
以下来自官方介绍的特性:
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 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-Plus �� 为简化开发而生
那么废话不多说,小编来介绍下,这个Mybatis-Plus如何快速上手。
快速上手
1.数据准备
该内容可以在navicat中操作
SQL -- 删除数据库(如果存在) DROP DATABASE IF EXISTS mybatis_test; -- 创建数据库,并设置默认字符集为utf8mb4 CREATE DATABASE mybatis_test DEFAULT CHARACTER SET utf8mb4; -- 使用创建的数据库 USE mybatis_test; -- 删除表(如果存在) DROP TABLE IF EXISTS user_info; -- 创建用户信息表 CREATE TABLE `user_info` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `username` VARCHAR(127) NOT NULL, `password` VARCHAR(127) NOT NULL, `age` TINYINT(4) NOT NULL, `gender` TINYINT(4) DEFAULT '0' COMMENT '1-男 2-女 0-默认', `phone` VARCHAR(15) DEFAULT NULL, `delete_flag` TINYINT(4) DEFAULT 0 COMMENT '0-正常,1-删除', `create_time` DATETIME DEFAULT now(), `update_time` DATETIME DEFAULT now(), PRIMARY KEY (`id`) ) ENGINE = INNODB DEFAULT CHARSET = utf8mb4; -- 插入用户数据 INSERT INTO mybatis_test.user_info(`username`, `password`, `age`, `gender`, `phone`) VALUES ('admin', 'admin', 18, 1, '18612340001'); INSERT INTO mybatis_test.user_info(`username`, `password`, `age`, `gender`, `phone`) VALUES ('zhangsan', 'zhangsan', 18, 1, '18612340002'); INSERT INTO mybatis_test.user_info(`username`, `password`, `age`, `gender`, `phone`) VALUES ('lisi', 'lisi', 18, 1, '18612340003'); INSERT INTO mybatis_test.user_info(`username`, `password`, `age`, `gender`, `phone`) VALUES ('wangwu', 'wangwu', 18, 1, '18612340004'); |
2.项目准备
创建一个Springboot项目
然后引入相关依赖
依赖引入(官网自有提供)
Spring Boot2:
XML <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.12</version> </dependency> |
Spring Boot3:
XML <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-spring-boot3-starter</artifactId> <version>3.5.12</version> </dependency> |
MySQL驱动:
XML <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <version>8.3.0</version> </dependency> |
3.配置文件:
application.yml:
YAML spring: application: name: MybatisPlus datasource: url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false username: root password: '9974' driver-class-name: com.mysql.cj.jdbc.Driver mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl |
application.properties:
Properties spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datesource.url=jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false spring.datasource.username=root spring.datasource.password='1234' mybatis-plus.configuration.log-impl:org.apache.ibatis.logging.stdout.StdOutImpl |
3.基本代码准备:
新建一个model包,新建一个UserInfo类
UserInfo:
Java import lombok.Data; import java.util.Date; @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包,同时新建一个UserInfoMapper
UserInfoMapper:
Java @Mapper public interface UserInfoMapper extends BaseMapper<UserInfo> { } |
至此,基本代码就写完了。
那么此时,如何使用呢?这里就不写接口了,在测试类中进行代码测试。
CRUD:
生成一个UserInfoMapperTest测试类
查询:
由于是mybatis-plus为我们提供了许多已经定制好的语句,这里直接就拿来用即可。
userInfoMapper
TypeScript @SpringBootTest class UserInfoMapperTest { @Autowired private UserInfoMapper userInfoMapper; //查 @Test void testSelectById(){ System.out.println(userInfoMapper.selectById(1)); } } |
那么值得注意的是,查询出来的结果及其结果样式,与上篇文章查询的结果,区别不大,所以不做展示
同时想要更多的详细信息,了解select提供的参数,可以访问官网了解:https://baomidou.com/guides/data-interface/#select
增加:
TypeScript //增 @Test void testInsert(){ UserInfo userinfo=new UserInfo(); userinfo.setUsername("python"); userinfo.setPassword("123456"); userinfo.setAge(19); userinfo.setGender(1); //返回结果为影响的行数 System.out.println(userInfoMapper.insert(userinfo)); } |
在增加这里,要注意一点,如若未指明ID(存在主键),那么mybatis-plus会通过一些策略进行生成ID
默认策略:
MyBatis-Plus 默认采用 IdType.ASSIGN_ID 作为主键生成策略,它会使用雪花算法(Snowflake)生成一个64位的Long型数字作为唯一ID。这意味着即使你没有手动为实体类设置ID值,在插入数据时MyBatis-Plus也会自动生成一个唯一的ID。
自定义主键生成策略:
Java //存在自增ID,要显式告诉mybatis-plus @TableId(type = IdType.AUTO) private Integer id; |
删除:
Java //删除 @Test void testDelete(){ System.out.println(userInfoMapper.deleteById(9)); } |
这里是简单演示下通过ID删除,它的参数还可以传是入一个列表(进行批量删除)等等,读者可以进行官网详细阅读。
https://baomidou.com/guides/data-interface/#delete
更新:
TypeScript //更新 @Test void testUpdate(){ UserInfo userinfo=new UserInfo(); userinfo.setId(9); userinfo.setUsername("JS"); userinfo.setPassword("JS1234"); userinfo.setAge(20); System.out.println(userInfoMapper.updateById(userinfo)); } |
更多详细方法,访问该官网:https://baomidou.com/guides/data-interface/#update-1
那么在mybatis中,我们演示了,如何可以重命名参数,那么mybatis-plus提供了对应的注解进行修改。
重命名表名:
Java @Data @TableName("user_Info") public class UserInfo { } |
重命名字段名:
TypeScript @Data @TableName("user_Info") public class UserInfo { //存在自增ID,要显式告诉plus @TableId(type = IdType.AUTO) private Integer id; @TableField("username") private String username; } |
以上是简单的增删查改语句,那么遇到一些复杂的话,那么就是需要用到条件构造器了。
条件构造器:
以下是来自官方的解释:
MyBatis-Plus 提供了一套强大的条件构造器(Wrapper),用于构建复杂的数据库查询条件。Wrapper 类允许开发者以链式调用的方式构造查询条件,无需编写繁琐的 SQL 语句,从而提高开发效率并减少 SQL 注入的风险。
在 MyBatis-Plus 中,Wrapper 类是构建查询和更新条件的核心工具。以下是主要的 Wrapper 类及其功能:
- AbstractWrapper:这是一个抽象基类,提供了所有 Wrapper 类共有的方法和属性。它定义了条件构造的基本逻辑,包括字段(column)、值(value)、操作符(condition)等。所有的 QueryWrapper、UpdateWrapper、LambdaQueryWrapper 和 LambdaUpdateWrapper 都继承自 AbstractWrapper。
- QueryWrapper:专门用于构造查询条件,支持基本的等于、不等于、大于、小于等各种常见操作。它允许你以链式调用的方式添加多个查询条件,并且可以组合使用 and 和 or 逻辑。
- UpdateWrapper:用于构造更新条件,可以在更新数据时指定条件。与 QueryWrapper 类似,它也支持链式调用和逻辑组合。使用 UpdateWrapper 可以在不创建实体对象的情况下,直接设置更新字段和条件。
- LambdaQueryWrapper:这是一个基于 Lambda 表达式的查询条件构造器,它通过 Lambda 表达式来引用实体类的属性,从而避免了硬编码字段名。这种方式提高了代码的可读性和可维护性,尤其是在字段名可能发生变化的情况下。
- LambdaUpdateWrapper:类似于 LambdaQueryWrapper,LambdaUpdateWrapper 是基于 Lambda 表达式的更新条件构造器。它允许你使用 Lambda 表达式来指定更新字段和条件,同样避免了硬编码字段名的问题。
那么接下来看看如何使用吧。
QueryWrapper:
构建查询条件,这里的查询条件不仅仅作用于select语句。
场景一:
查询age==18,以及模糊匹配username='java'
TypeScript @Test void testQueryWrapper(){ QueryWrapper<UserInfo> queryWrapper=new QueryWrapper<>(); queryWrapper.select("id,username,password,age,gender") .eq("age",18) .like("username","python"); userInfoMapper.selectList(queryWrapper).forEach(System.out::println); } |
System.out::println:
这个是Java8引入的方法引用,用于直接引用已有的方法,它是属于函数式编程的一部分。
对于方法引用,以及函数式编程,解释如下:
函数式编程:
函数式编程 是一种编程范式(Programming Paradigm),它强调“函数是一等公民”,即函数可以像变量一样被传递、赋值、作为参数或返回值。
方法引用:
方法引用 是对已有方法的引用,它可以简化 Lambda 表达式的写法,使代码更清晰。
常见的方法引用类型:

点击图片可查看完整电子表格
like:左右通配匹配。
likeRight:右匹配:name%
likeLeft:左匹配:%name
场景二:
年龄小于21岁以下的,把deleteFlag设置为1(通过对象属性设置)
TypeScript @Test void testQueryWrapper2() { QueryWrapper<UserInfo> queryWrapper=new QueryWrapper<>(); UserInfo userInfo=new UserInfo(); queryWrapper.lt("age",21); userInfo.setDeleteFlag(1); System.out.println(userInfoMapper.update(userInfo, queryWrapper)); } |
场景三:
删除年龄等于21的
Java @Test void testQueryWrapper3() { QueryWrapper<UserInfo> queryWrapper=new QueryWrapper<>(); queryWrapper.eq("age",21); System.out.println(userInfoMapper.delete(queryWrapper)); } |
UpdateWrapper:
场景1:
设置年龄21,当名字为java的时候
TypeScript @Test void updateQueryWrapper(){ UpdateWrapper<UserInfo> updateWrapper=new UpdateWrapper<>(); updateWrapper.set("age",21) .eq("username","java"); System.out.println(userInfoMapper.update(updateWrapper)); } |
场景二:
设置年龄40,gender=1,通过批量修改
TypeScript @Test void updateQueryWrapper2(){ UpdateWrapper<UserInfo> updateWrapper=new UpdateWrapper<>(); updateWrapper.set("age",40).set("gender",1) .in("id", List.of(4,6,7)); System.out.println(userInfoMapper.update(updateWrapper)); } |
场景三:
设置SQL片段语句,age=age+10,通过ID进行批量修改
TypeScript @Test void updateWrapper3(){ UpdateWrapper<UserInfo> updateWrapper=new UpdateWrapper<>(); updateWrapper.setSql("age=age+10") .in("id",List.of(4,6,7)); System.out.println(userInfoMapper.update(updateWrapper)); } |
lambdaWrapper:
LambdaQueryWrapper:
示例,查询数据库中,年龄等于18的相关信息:
Java @Test void lambdaQueryWrapper(){ LambdaQueryWrapper<UserInfo> queryWrapper=new LambdaQueryWrapper<>(); System.out.println(queryWrapper.select(UserInfo::getId, UserInfo::getUsername, UserInfo::getAge, UserInfo::getGender,UserInfo::getCreateTime) .eq(UserInfo::getAge, 18)); userInfoMapper.selectList(queryWrapper).forEach(System.out::println); } |
LamdaUpdateWrapper:
示例:修改数据库密码和年龄,当名字为王五的时候
这里使用UpdateWrapper.lambda()方法去做
Java @Test void lambdaUpdateWrapper(){ UpdateWrapper<UserInfo> updateWrapper=new UpdateWrapper<>(); updateWrapper.lambda() .set(UserInfo::getPassword,"12345") .set(UserInfo::getAge,"20") .eq(UserInfo::getUsername,"王五"); System.out.println(userInfoMapper.update(updateWrapper)); } |
对于使用LambdaUpdateWrapperd类来说,上面内容只需去掉.lamda()即可
那么对于条件构造器这里呢,小编就讲到这,详细的可以看官方文档:https://baomidou.com/guides/wrapper/#_top
既然Mybatis-plus这么好用,那么提供的方法是否就一定满足业务需求了呢?
显然,是很难做到的,所以Mybatis也是支持自定义SQL语句。
自定义SQL语句
简单介绍几个场景
1.查询username等于java的
Java */ @Mapper public interface UserInfoMapper extends BaseMapper<UserInfo> { //自定义SQL语句 @Select("select id,username,password,age " + "from user_info ${ew.customSqlSegment}") List<UserInfo> selectByCustom(@Param(Constants.WRAPPER)Wrapper wrapper); } |
测试类:
TypeScript @Test void selectByCustom() { QueryWrapper<UserInfo> queryWrapper=new QueryWrapper<>(); queryWrapper.eq("username","java"); userInfoMapper.selectByCustom(queryWrapper).forEach(System.out::println); } |
@Param(Constants.WRAPPER):
Constants.WRAPPER="ew",写上这个,是告诉Mybatis-plus,这个是Wrapper对象,并且它的参数固定名为
"ew"(即 Entity Wrapper 的缩写)
${ew.customSqlSegment}:
这是一个占位符把传进来的 Wrapper 对象转换成 SQL 条件语句,并插入到当前 SQL 的位置上。
$符号内的ew是来自@Parm里的
值得注意的是,最好是#{},为了防止SQL注入的占位符。
2.通过XML来查询
配置文件:
YAML mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl mapper-locations: classpath*:/mapper/**/*.xml |
UserInfoMapper接口类:
Java List<UserInfo> selectByCustom2(@Param(Constants.WRAPPER)Wrapper wrapper); |
xml文件:
XML <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.nanxi.mybatisplus.mapper.UserInfoMapper"> <select id="selectByCustom2" resultType="com.nanxi.mybatisplus.model.UserInfo"> select id,username,password,age from user_info ${ew.customSqlSegment} </select> </mapper> |
测试类:
TypeScript @Test void selectByCustom2() { QueryWrapper<UserInfo> queryWrapper=new QueryWrapper<>(); queryWrapper.eq("username","java"); userInfoMapper.selectByCustom2(queryWrapper).forEach(System.out::println); } |
3.表达式赋值
Java @Update("update user_info set age=age+#{age} ${ew.customSqlSegment}") Integer selectByCustom3(@Param("age") Integer age,@Param(Constants.WRAPPER)Wrapper wrapper); |
测试类:
Java @Test void selectByCustom3() { UpdateWrapper<UserInfo> updateWrapper=new UpdateWrapper<>(); updateWrapper.eq("username","java"); System.out.println(userInfoMapper.selectByCustom3(10, updateWrapper)); } |
至此,对于Mybatis-plus的简单到这里,更多信息,可以访问官网进行详细了解