Mybatis-Plus简单介绍
前一篇文章中,小编介绍到了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
com.baomidou
mybatis-plus-boot-starter
3.5.12
Spring Boot3:
XML
com.baomidou
mybatis-plus-spring-boot3-starter
3.5.12
MySQL驱动:
XML
com.mysql
mysql-connector-j
8.3.0
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 {
}
至此,基本代码就写完了。
那么此时,如何使用呢?这里就不写接口了,在测试类中进行代码测试。
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 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 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 queryWrapper=new QueryWrapper();
queryWrapper.eq("age",21);
System.out.println(userInfoMapper.delete(queryWrapper));
}
UpdateWrapper:
场景1:
设置年龄21,当名字为java的时候
TypeScript
@Test
void updateQueryWrapper(){
UpdateWrapper updateWrapper=new UpdateWrapper();
updateWrapper.set("age",21)
.eq("username","java");
System.out.println(userInfoMapper.update(updateWrapper));
}
场景二:
设置年龄40,gender=1,通过批量修改
TypeScript
@Test
void updateQueryWrapper2(){
UpdateWrapper 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 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 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 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 {
//自定义SQL语句
@Select("select id,username,password,age " +
"from user_info ${ew.customSqlSegment}")
List selectByCustom(@Param(Constants.WRAPPER)Wrapper wrapper);
}
测试类:
TypeScript
@Test
void selectByCustom() {
QueryWrapper 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 selectByCustom2(@Param(Constants.WRAPPER)Wrapper wrapper);
xml文件:
XML
select id,username,password,age from
user_info ${ew.customSqlSegment}
测试类:
TypeScript
@Test
void selectByCustom2() {
QueryWrapper 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 updateWrapper=new UpdateWrapper();
updateWrapper.eq("username","java");
System.out.println(userInfoMapper.selectByCustom3(10, updateWrapper));
}
至此,对于Mybatis-plus的简单到这里,更多信息,可以访问官网进行详细了解
- LambdaUpdateWrapper:类似于 LambdaQueryWrapper,LambdaUpdateWrapper 是基于 Lambda 表达式的更新条件构造器。它允许你使用 Lambda 表达式来指定更新字段和条件,同样避免了硬编码字段名的问题。
- LambdaQueryWrapper:这是一个基于 Lambda 表达式的查询条件构造器,它通过 Lambda 表达式来引用实体类的属性,从而避免了硬编码字段名。这种方式提高了代码的可读性和可维护性,尤其是在字段名可能发生变化的情况下。
- UpdateWrapper:用于构造更新条件,可以在更新数据时指定条件。与 QueryWrapper 类似,它也支持链式调用和逻辑组合。使用 UpdateWrapper 可以在不创建实体对象的情况下,直接设置更新字段和条件。
- QueryWrapper:专门用于构造查询条件,支持基本的等于、不等于、大于、小于等各种常见操作。它允许你以链式调用的方式添加多个查询条件,并且可以组合使用 and 和 or 逻辑。
- AbstractWrapper:这是一个抽象基类,提供了所有 Wrapper 类共有的方法和属性。它定义了条件构造的基本逻辑,包括字段(column)、值(value)、操作符(condition)等。所有的 QueryWrapper、UpdateWrapper、LambdaQueryWrapper 和 LambdaUpdateWrapper 都继承自 AbstractWrapper。
- 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
- 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
- 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
- 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
- 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
- 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
- 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
- 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
- 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
- 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作