持久层框架MyBatisPlus

简介: MyBatisPlus是MyBatis的增强工具,简化单表CRUD操作,支持条件构造器、分页、逻辑删除等功能,提升开发效率。

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

1.快速入门1.1 入门案例

mp.sql

(6 KB)

mp-demo.zip

(52 KB)

首先我们根据提供的资料导入一下工程案例,一起看下实现下列功能的代码逻辑:新增用户功能根据id查询用户根据id批量查询用户根据id更新用户根据id删除用户代码执行流程如下:当我们打开:UserMapper_20231023_150307.xml 文件后,可以看到熟悉的代码但是我们不禁要思考一个问题,简单的单表的增删改查,他的SQL语句基本固定,这种是否可以优化呢?当然是可以的,这就是这一小节MP要做的事情。而要引入MP框架并应用起来,遵循下面的步骤即可。1-引入MybatisPlus的起步依赖MyBatisPlus官方提供了starter,其中集成了Mybatis和MybatisPlus的所有功能,并且实现了自动装配效果。因此我们可以用MybatisPlus的starter代替Mybatis的starter:原来的mybatis依赖可以删除掉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 (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大概如下分析:因为是查询,且查询指定字段,所以这里考虑QueryWrapper更新用户名为jack的用户的余额为2000上述案例的SQL大概如下分析:因为更新的where条件中带查询,所以可以用QueryWrapper更新id为1,2,4的用户的余额,扣200上述案例的SQL大概如下分析:这个SQL更新条件不需要做额外的查询,所以UpdateWrapper可以直接搞定,并且这里是账户余额扣减200不是直接设置成两百,所以我们的更新参数第一个user给null就好如果这里同时需要设置用户姓名拼接:***,就可以初始化一个User对象,然后做拼接,最后传递进去就可以2.2 自定义SQL这个我们在项目二会使用到我们可以利用MyBatisPlus的Wrapper来构建复杂的Where条件,然后自己定义SQL语句中剩下的部分。需求:将id在指定范围的用户(例如1、2、4 )的余额扣减指定值正常我们的SQL语句如下如果我们采用自定义的,就会将整个Where条件抽取,实现细节如下①基于Wrapper构建where条件②创建接口方法,在mapper方法参数中用Param注解声明wrapper变量名称,必须是ew③自定义SQL,并使用Wrapper条件,这里可以二选一一、动态SQL二、注解形式(直接在接口方法增加@Update注解)2.3 Service接口理论分析前面我们的MP接口都是在mapper层编写的,MP也为我们提供了一些更高效的service层方法比如上述的批量新增、批量更新、查询单个、批量删除、分页等都是非常实用的。而要去实现这个功能就不能像原来Mapper层一样直接继承BaseMapper了,因为接口是有实现类的,所以我们遵循下面这一套规范:用户的接口继承:IService用户的接口实现类继承:ServiceImpl案例实操IService的Lambda查询需求:实现一个根据复杂条件查询用户的接口,查询条件如下:name:用户名关键字,可以为空status:用户状态,可以为空minBalance:最小余额,可以为空maxBalance:最大余额,可以为空根据这个要求,我们不难分析出它的SQL接下来我们在service层做一个简单实现IService的Lambda更新需求:根据id修改用户余额的接口,要求如下输入条件为id、username、balance每次将指定用户的余额扣减balance如果扣减后余额为0,则将用户status修改为冻结状态(2)代码实现大致如下IService批量新增需求:批量插入10万条用户数据,并作出对比:普通for循环插入IService的批量插入开启rewriteBatchedStatements=true参数,在连接信息的url后拼接:&rewriteBatchedStatements=true批处理方案分析:普通for循环逐条插入速度极差,不推荐MP的批量新增,基于预编译的批处理,性能不错配置jdbc参数,开rewriteBatchedStatements,性能最好所以这里我们先配置一下链接参数:然后编写一个批量测试的方法3.拓展功能3.1 代码生成前面我们写的这一大堆代码都是自己手动写出来的,这小节我们将借助于一个插件帮助开发们自动生成下面的代码首先我们安装一个插件安装之后,可以在other点击:config Database,配置数据库然后点击:code generator,生成代码,规则如下3.2 静态工具(了解)前面我们在mapper层或者service完成了各种CRUD,但是MP也提供了一个静态工具类:Db,这里面也封装了日常需要使用的接口方法,以解决:service之间相互引入,嵌套引入导致的循环依赖问题。其API如下当我们需要使用时,如下图即可:3.3 逻辑删除逻辑删除就是基于代码逻辑模拟删除效果,但并不会真正删除数据。思路如下:在表中添加一个字段标记数据是否被删除当删除数据时把标记置为1查询时只查询标记为0的数据例如逻辑删除字段为deleted:删除操作:查询操作:MybatisPlus提供了逻辑删除功能,无需改变方法调用的方式,而是在底层帮我们自动修改CRUD的语句。我们要做的就是在application.yaml文件中配置逻辑删除的字段名称和值即可:注意:逻辑删除本身也有自己的问题,比如:会导致数据库表垃圾数据越来越多,影响查询效率SQL中全都需要对逻辑删除字段做判断,影响查询效率因此,生产环境采用逻辑删除功能比较多,但如果数据不能删除,也可以把数据迁移到其它表中。3.4 枚举处理器当数据库是status是int类型,为了实现PO类中的枚举类型变量与数据库字段的转换,我们就可以借助:@EnumValue 注解将其做映射,无需特殊处理其实现步骤共两步①给枚举中的与数据库对应value值添加@EnumValue注解②在application.yml中配置全局枚举处理器:3.5 JSON处理器当数据库中有一个JSON类型字段时,MP依然做了支持,只需要在对应属性值追加下面截图注解即可。4.插件功能MP提供的内置拦截器如下,借助于这些拦截器我们就可以实现一些比较有意思的功能了。这里我们给大家讲解一下使用频率最高的分页插件。【项目二会使用到动态表名插件-做分库分表】4.1 分页插件首先,要在配置类中注册MyBatisPlus的核心插件,同时添加分页插件:接着,就可以使用分页的API了:大概实现代码如下:4.2 通用分页实体前面我们做了简单的分页查询之后接下来通过一个案例做一下我们今天整体功能的收尾。需求如下

参数

说明

请求方式

GET

请求路径

/users/page

请求入参

{ "pageNo":1, "pageSize":5, "sortBy":"balance", "isAsc":false, "name":"jack", "status":1}

响应出参

{ "total":1005, "pages":201, "list":[ { "id":1, "username":"Jack", "info":{ "age":21, "gender":"male", "intro":"佛系青年" }, "status":"正常", "balance":2000 }, { "id":2, "username":"Rose", "info":{ "age":20, "gender":"female", "intro":"文艺青年" }, "status":"冻结", "balance":1000 } ]}

特殊说明

如果排序字段为空,默认按照更新时间排序排序字段不为空,则按照排序字段排序


相关文章
|
12天前
|
数据采集 人工智能 安全
|
7天前
|
机器学习/深度学习 人工智能 前端开发
构建AI智能体:七十、小树成林,聚沙成塔:随机森林与大模型的协同进化
随机森林是一种基于决策树的集成学习算法,通过构建多棵决策树并结合它们的预测结果来提高准确性和稳定性。其核心思想包括两个随机性:Bootstrap采样(每棵树使用不同的训练子集)和特征随机选择(每棵树分裂时只考虑部分特征)。这种方法能有效处理大规模高维数据,避免过拟合,并评估特征重要性。随机森林的超参数如树的数量、最大深度等可通过网格搜索优化。该算法兼具强大预测能力和工程化优势,是机器学习中的常用基础模型。
344 164
|
6天前
|
机器学习/深度学习 自然语言处理 机器人
阿里云百炼大模型赋能|打造企业级电话智能体与智能呼叫中心完整方案
畅信达基于阿里云百炼大模型推出MVB2000V5智能呼叫中心方案,融合LLM与MRCP+WebSocket技术,实现语音识别率超95%、低延迟交互。通过电话智能体与座席助手协同,自动化处理80%咨询,降本增效显著,适配金融、电商、医疗等多行业场景。
345 155
|
7天前
|
编解码 人工智能 自然语言处理
⚽阿里云百炼通义万相 2.6 视频生成玩法手册
通义万相Wan 2.6是全球首个支持角色扮演的AI视频生成模型,可基于参考视频形象与音色生成多角色合拍、多镜头叙事的15秒长视频,实现声画同步、智能分镜,适用于影视创作、营销展示等场景。
581 4
|
15天前
|
SQL 自然语言处理 调度
Agent Skills 的一次工程实践
**本文采用 Agent Skills 实现整体智能体**,开发框架采用 AgentScope,模型使用 **qwen3-max**。Agent Skills 是 Anthropic 新推出的一种有别于mcp server的一种开发方式,用于为 AI **引入可共享的专业技能**。经验封装到**可发现、可复用的能力单元**中,每个技能以文件夹形式存在,包含特定任务的指导性说明(SKILL.md 文件)、脚本代码和资源等 。大模型可以根据需要动态加载这些技能,从而扩展自身的功能。目前不少国内外的一些框架也开始支持此种的开发方式,详细介绍如下。
1019 7