持久层框架MyBatisPlus

简介: MyBatisPlus是基于MyBatis的增强ORM框架,简化单表增删改查操作。通过继承BaseMapper即可实现CRUD,支持注解映射与全局配置,提供QueryWrapper、UpdateWrapper等条件构造器,灵活构建查询条件,并可结合自定义SQL满足复杂业务需求,大幅提升开发效率。

前面我们学习过的ORM[Object Relational Mapping(对象关系映射)]持久层框架MyBatis,它可以帮助我们完成单表、多表、动态SQL的业务逻辑处理,与之平级的还有Hibernate,和这节我们要学习的MyBatisPlus了。

1.快速入门
1.1 入门案例

首先我们根据提供的资料导入一下工程案例,一起看下实现下列功能的代码逻辑:
● 新增用户功能
● 根据id查询用户
● 根据id批量查询用户
● 根据id更新用户
● 根据id删除用户
代码执行流程如下:

当我们打开:UserMapper_20231023_150307.xml 文件后,可以看到熟悉的代码

但是我们不禁要思考一个问题,简单的单表的增删改查,他的SQL语句基本固定,这种是否可以优化呢?当然是可以的,这就是这一小节MP要做的事情。而要引入MP框架并应用起来,遵循下面的步骤即可。
1-引入MybatisPlus的起步依赖
MyBatisPlus官方提供了starter,其中集成了Mybatis和MybatisPlus的所有功能,并且实现了自动装配效果。因此我们可以用MybatisPlus的starter代替Mybatis的starter:
● 原来的mybatis依赖可以删除掉


com.baomidou
mybatis-plus-boot-starter
3.5.3.1

2-继承BaseMapper
然后我们在自己的mapper接口中继承BaseMapper,并声明泛型对应的实体类就可以有常见的CRUD代码了。

接下来我们就用MP依次替代上述增删改查的原始代码
● 新增用户功能

● 根据id查询用户

● 根据id批量查询用户

● 根据id更新用户

● 根据id删除用户

整体改造完之后,我们就可以把之前:UserMapper_20231023_150307.xml 中的代码都删掉了,是不是很简洁

1.2 常见注解
通过上面的案例我们可以发现mp的使用很便捷,用户基本是无感知的,那他是如何做到表跟属性值的映射的呢?MyBatisPlus通过扫描实体类,并基于反射获取实体类信息作为数据库表信息。

但是上述的都是正常情况,如果存在一些异常:如表名跟实体类不一样、实体类部分字段表中没有等,就可以通过一些常见注解来完成映射了,MybatisPlus中比较常用的几个注解如下:
● @TableName:用来指定表名
● @TableId:用来指定表中的主键字段信息
● @TableField:用来指定表中的普通字段信息
假设表结构如下

则对应的实体类可以映射如下

其中
IdType枚举:
● AUTO:数据库自增长
● INPUT:通过set方法自行输入
● ASSIGN_ID:分配 ID,接口IdentifierGenerator的方法nextId来生成id,默认实现类为DefaultIdentifierGenerator
雪花算法使用@TableField的常见场景:
● 成员变量名与数据库字段名不一致
● 成员变量名以is开头,且是布尔值
● 成员变量名与数据库关键字冲突
● 成员变量不是数据库字段
1.3 常见配置
MyBatisPlus的配置项继承了MyBatis原生配置和一些自己特有的配置。例如:
mybatis-plus:
type-aliases-package: com.itheima.mp.domain.po # 别名扫描包
mapper-locations: "classpath:/mapper/**/.xml" # Mapper.xml文件地址,默认值
configuration:
map-underscore-to-camel-case: true # 是否开启下划线和驼峰的映射
cache-enabled: false # 是否开启二级缓存
global-config:
db-config:
id-type: assign_id # id为雪花算法生成
update-strategy: not_null # 更新策略:只更新非空字段

具体可参考官方文档:使用配置 | MyBatis-Plus (baomidou.com)
2.核心功能
2.1 条件构造器
理论分析
MyBatisPlus支持各种复杂的where条件,可以满足日常开发的所有需求。当我们继承BaseMapper之后,就具备了一些常见的接口方法

这里的Wrapper就是各种条件构造器,他的子类继承体系如下

在这个体系中,AbstractWrapper定义了各种查询的条件,如:eq、in、between、like、gt、lt等。也就是说借助于他可以完成单表各种场景的查询条件组装。那为什么他又有QueryWrapper、UpdateWrapper呢?这是因为我们一个完整的查询语句是:SELECT 字段 FROM 表名 WHERE 条件
QueryWrapper可以帮助我们声明要查询的具体字段,避免查询全部字段,导致IO开销过大,从而影响SQL性能的问题。同理UpdateWrapper一样,可以帮我们更新指定字段。

案例实操
接下来我们就通过几个案例,来实际体验一下吧
● 查询出名字中带o的,存款大于等于1000元的人的id、username、info、balance字段
上述案例的SQL大概如下
SELECT id, username, info, balance
FROM user
WHERE
username like '%o%'
AND balance >= 1000
分析:因为是查询,且查询指定字段,所以这里考虑QueryWrapper
@Test
void testQueryWrapper() {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper
.select("id", "username", "info", "balance")
.like("username", "o")
.ge("balance", "1000");
List users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
● 更新用户名为jack的用户的余额为2000
上述案例的SQL大概如下
UPDATE user
SET balance = 2000
WHERE username = "jack"
分析:因为更新的where条件中带查询,所以可以用QueryWrapper
@Test
void testQueryWrapper2() {
// 1-数据
User user = new User();
user.setBalance(2000);
// 2-条件
QueryWrapper wrapper = new QueryWrapper().eq("username", "jack");
// 3-更新
userMapper.update(user, wrapper);
}
● 更新id为1,2,4的用户的余额,扣200
上述案例的SQL大概如下
UPDATE user
SET balance = balance - 200
WHERE id in (1, 2, 4)
分析:这个SQL更新条件不需要做额外的查询,所以UpdateWrapper可以直接搞定,并且这里是账户余额扣减200不是直接设置成两百,所以我们的更新参数第一个user给null就好
@Test
void testUpdateWrapper() {
UpdateWrapper updateWrapper = new UpdateWrapper()
.setSql("balance = balance - 200")
.in("id", Arrays.asList(1L, 2L, 3L));
userMapper.update(null, updateWrapper);
}
如果这里同时需要设置用户姓名拼接:*,就可以初始化一个User对象,然后做拼接,最后传递进去就可以
2.2 自定义SQL
这个我们在项目二会使用到
我们可以利用MyBatisPlus的Wrapper来构建复杂的Where条件,然后自己定义SQL语句中剩下的部分。
需求:将id在指定范围的用户(例如1、2、4 )的余额扣减指定值
正常我们的SQL语句如下

相关文章
|
安全 算法 网络安全
一文读懂 RSA 加密:非对称加密的基石
RSA是应用最广泛的非对称加密算法,由Rivest、Shamir和Adleman于1977年提出。它基于大数分解难题,使用公钥加密、私钥解密,解决密钥分发问题,广泛用于HTTPS、数字签名等安全通信场景,是现代网络安全的基石之一。
2682 0
|
2月前
|
监控 算法 Unix
Thread.sleep(0) 到底有什么
Thread.Sleep用于让线程暂停执行一段时间,不参与CPU竞争。Sleep(1000)并不保证精确唤醒时间,因系统调度受优先级和资源影响;而Sleep(0)则触发系统立即重新分配CPU,给予其他线程执行机会,避免界面假死。理解其原理有助于优化多线程程序性能与响应性。
|
2月前
|
监控 算法 Unix
Thread.sleep(0) 到底有什么用
Thread.Sleep用于让线程暂停执行一段时间,期间不参与CPU竞争。Sleep(1000)不保证精确唤醒时间,受系统调度影响;而Sleep(0)会触发系统立即重新分配CPU,给其他线程执行机会,避免界面假死。两者作用不可忽视。
|
2月前
|
监控 算法 Unix
Thread.sleep(0) 到底有什么用(读完
本简介旨在简要介绍所提供的内容,突出其核心要点与价值。通过精炼语言,概括主题思想,帮助读者快速理解主要内容,适用于推广、导读或信息传递场景,力求在240字符内清晰传达关键信息。
|
2月前
|
缓存 算法 搜索推荐
线程池
线程池是将多个线程统一管理的“池化”技术,避免频繁创建销毁线程带来的开销。Java中通过`ExecutorService`和`ThreadPoolExecutor`等类实现,核心原理是复用线程、任务队列调度及合理的拒绝策略。`ScheduledThreadPoolExecutor`支持延时与周期性任务,基于`DelayedWorkQueue`实现延迟调度。`Executors`工厂类提供多种线程汛建造方法,如固定大小、缓存型、单线程等,适用于不同并发场景,提升系统性能与资源利用率。
|
2月前
|
JSON 缓存 前端开发
什么是跨域
CORS(跨域资源共享)是W3C标准,允许浏览器向跨源服务器发起XMLHttpRequest请求,突破AJAX同源限制。需浏览器和服务器共同支持,主流浏览器均已兼容。通信过程由浏览器自动完成,开发者无需改变代码。分为简单请求与非简单请求:前者直接发送带Origin头的请求;后者先发起OPTIONS预检,确认后才执行实际请求。服务器通过响应头如Access-Control-Allow-Origin等控制跨域权限。相比仅支持GET的JSONP,CORS更强大灵活,支持所有HTTP方法,且可携带认证信息。
|
2月前
|
关系型数据库 MySQL Java
开发环境搭建
工欲善其事,必先利其器。学习前请确保电脑内存16G以上(建议32G),推荐使用便携显示器分屏开发以提升效率。下载并配置虚拟机(IP:192.168.101.68)、安装VMware、FinalShell远程连接,导入CentOS7虚拟机并启动Docker、MySQL等服务。IDEA中配置JDK11、Maven(3.8.6)及本地仓库,设置编码与自动导包。安装Git并配置账号信息。通过Gitee Fork黑马商城项目,克隆到本地,创建hmall数据库并导入SQL脚本。前端使用nginx部署,启动后访问http://localhost:18080登录测试。
|
2月前
|
NoSQL Redis Docker
Redis集群搭建
Redis主从实现读写分离,提升并发能力;哨兵保障高可用,自动故障恢复;分片集群支持海量数据存储与高并发读写,三者结合构建高性能、高可用分布式缓存架构。
|
2月前
|
canal 消息中间件 关系型数据库
配置数据同步环境
配置Canal+RabbitMQ实现MySQL数据同步,通过开启Binlog行模式、创建专用用户并授权,部署Canal监听指定表变更,将数据实时发送至RabbitMQ指定队列,确保hm-item库中item_sync表的增删改操作同步至消息队列,支持后续数据消费与处理。
|
2月前
|
消息中间件 Java 数据安全/隐私保护
RabbitMQ集群部署
本文介绍RabbitMQ集群部署与高可用方案,涵盖普通集群搭建、Erlang Cookie配置、节点发现机制及安全设置。通过静态配置实现三节点集群,并详解镜像模式(exactly、all、nodes)提升高可用性,避免单点故障。同时引入3.8版本后的仲裁队列,简化配置,实现数据冗余与自动主从切换,保障消息服务的稳定性与可靠性。