1. 了解Mybatis-Plus
1.1 Mybatis-Plus介绍
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
官网: https://mybatis.plus/ 或 https://mp.baomidou.com/
愿景
我们的愿景是成为 MyBatis 最好的搭档,就像 魂斗罗 中的 1P、2P,基友搭配,效率翻倍。
1.2 代码以及文档
文档地址:https://mybatis.plus/guide/
源码地址:https://github.com/baomidou/mybatis-plus
1.3 特性
- 无侵入 :只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小 :启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
- 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
- 支持多种数据库 :支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer2005、SQLServer 等多种数据库
- 支持主键自动生成 :支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
- 支持 XML 热加载:Mapper 对应的 XML 支持热加载,对于简单的 CRUD 操作,甚至可以无 XML 启动
- 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
- 支持自定义全局通用操作 :支持全局通用方法注入( Write once, use anywhere )
- 支持关键词自动转义 :支持数据库关键词(order、key……)自动转义,还可自定义关键词
- 内置代码生成器 :采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
- 内置分页插件 :基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List查询
- 内置性能分析插件 :可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
- 内置全局拦截插件 :提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
- 内置 Sql 注入剥离器:支持 Sql 注入剥离,有效预防 Sql 注入攻击
1.4 架构
1.5 作者
Mybatis-Plus是由baomidou(苞米豆)组织开发并且开源的,目前该组织大概有30人左右。
码云地址:https://gitee.com/organizations/baomidou
2. 快速开始
对于 Mybatis整合MP有常常有三种用法,分别是Mybatis+MP、Spring+Mybatis+MP、Spring Boot+Mybatis+MP。
2.1 创建数据库以及表
1 | -- 创建测试表 |
2.2 创建工程导入依赖
1 |
|
2.3 Mybatis + MP
下面演示,通过纯Mybatis与Mybatis-Plus整合。
2.3.1 创建子Module
1 |
|
log4j.properties:
1 | DEBUG,A1 = |
2.3.2 Mybatis实现查询User
2.3.2.1 编写mybatis-config.xml文件
1 |
|
2.3.2.2 编写User对象
使用lombok进行了进化bean操作。注意:注解不生效需要Idea安装lombok插件
1 | /** |
2.3.2.3 编写UserMapper接口
1 | /** |
2.3.2.4 编写UserMapper.xml文件
1 |
|
2.3.2.5 测试
1 | /** |
2.3.3 Mybatis+MP实现查询User
2.3.3.1 Mapper继承BaseMapper
将UserMapper继承BaseMapper,将拥有了BaseMapper中的所有方法
1 | /** |
2.3.3.2 MybatisSqlSessionFactoryBuilder进程构建
1 | /** |
运行报错:
解决:在 User对象中添加@TableName,指定数据库表名
简单说明:
由于使用了 MybatisSqlSessionFactoryBuilder进行了构建,继承的BaseMapper中的方法就载入到了SqlSession中,所以就可以直接使用相关的方法;
2.4 Spring + Mybatis + MP
引入了Spring框架,数据源、构建等工作就交给了Spring管理。
2.4.1 创建子Module
1 |
|
2.4.2 实现查询User
2.4.2.1 编写jdbc.properties
1 | com.mysql.jdbc.Driver = |
2.4.2.2 编写applicationContext.xml
1 |
|
2.4.2.3 编写User对象
1 | /** |
2.4.2.4 编写UserMapper接口
1 | /** |
2.4.2.5 测试
1 | /** |
注意:
测试报错需将jdbc.properties、applicationContext.xml复制到test/resources下
2.5 SpringBoot + Mybatis + MP
使用SpringBoot将进一步的简化MP的整合,需要注意的是,由于使用SpringBoot需要继承parent,所以需要重新创建工程,并不是创建子Module。
2.5.1 创建工程导入依赖
1 |
|
log4j.properties:
1 | DEBUG,A1 = |
2.5.2 编写application.properties
1 | mp-springboot = |
2.5.3 编写User对象
1 | /** |
2.5.4 编写UserMapper接口
1 | /** |
2.5.5 编写启动类
1 | /** |
2.5.6 测试
1 | /** |
3. 通用CRUD
通过前面的学习,我们了解到通过继承BaseMapper就可以获取到各种各样的单表操作,接下来我们将详细讲解这些操作。
3.1 插入操作
1 | /** |
数据已经写入到了数据库,但是, id的值不正确,我们期望的是数据库自增长,实际是MP生成了id的值写入到了数据库。
如何设置id的生成策略呢?
修改User对象:
1 | /** |
3.1.1 @TableField
在MP中通过@TableField注解可以指定字段的一些属性,常常解决的问题有2个:
- 对象中的属性名和字段名不一致的问题(非驼峰)
- 对象中的属性字段在表中不存在的问题
其他用法,如大字段不加入查询字段:
效果:
3.2 更新操作
在MP中,更新操作有2种,一种是根据id更新,另一种是根据条件更新。
3.2.1 根据id更新
1 | /** |
3.2.2 根据条件更新
1 | /** |
或者,通过UpdateWrapper进行更新:
1 | /** |
3.3 删除操作
3.3.1 deleteById
1 | /** |
3.3.2 deleteByMap
1 | /** |
3.3.3 delete
1 | /** |
3.3.4 deleteBatchIds
1 | /** |
3.4 查询操作
MP提供了多种查询操作,包括根据id查询、批量查询、查询单条数据、查询列表、分页查询等操作
3.4.1 selectById
1 | /** |
3.4.2 selectBatchIds
1 | /** |
3.4.3 selectOne
1 | /** |
3.4.4 selectCount
1 | /** |
3.4.5 selectList
1 | /** |
3.4.6 selectPage
配置分页插件:
1 | /** |
或者config配置分页插件
1 |
|
测试:
1 | /** |
3.5 SQL注入的原理
前面我们已经知道,MP在启动后会将BaseMapper中的一系列的方法注册到mappedStatements中,那么究竟是如何注入的呢?流程又是怎么样的?下面我们将一起来分析下。
在MP中,ISqlInjector负责SQL的注入工作,它是一个接口,AbstractSqlInjector是它的实现类,实现关系如下:
在 AbstractSqlInjector中,主要是由inspectInject()方法进行注入的,如下:
1 |
|
在实现方法中, methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass,tableInfo));
是关键,循环遍历方法,进行注入。
最终调用抽象方法injectMappedStatement进行真正的注入:
1 | /** |
查看该方法的实现:
以 SelectById为例查看:
1 | /** |
可以看到,生成了SqlSource对象,再将SQL通过addSelectMappedStatement方法添加到meppedStatements中
4. 配置
在MP中有大量的配置,其中有一部分是Mybatis原生的配置,另一部分是MP的配置,详情:https://mybatis.plus/config/
下面我们对常用的配置做讲解。
4.1 基本配置
4.1.1 configLocation
MyBatis 配置文件位置,如果您有单独的 MyBatis 配置,请将其路径配置到 configLocation 中。 MyBatis Configuration 的具体内容请参考MyBatis 官方文档
Spring Boot:
1 | #指定全局的配置文件 |
Spring MVC:
1 | <!--这里使用MP提供的sqlSessionFactory,完成了Spring与MP的整合--> |
4.1.2 mapperLocations
MyBatis Mapper 所对应的 XML 文件位置,如果您在 Mapper 中有自定义方法(XML 中有自定义实现),需要进行该配置,告诉 Mapper 所对应的 XML 文件位置。
Spring Boot:
1 | # 指定Mapper.xml文件的路径 |
Spring MVC:
1 | <!--这里使用MP提供的sqlSessionFactory,完成了Spring与MP的整合--> |
Maven 多模块项目的扫描路径需以 classpath*: 开头 (即加载多个 jar 包下的 XML 文件)
测试:
UserMapper.xml:
1 |
|
1 | /** |
4.1.3 typeAliasesPackage
MyBaits 别名包扫描路径,通过该属性可以给包中的类注册别名,注册后在 Mapper 对应的 XML 文件中可以直接使用类名,而不用使用全限定的类名(即 XML 中调用的时候不用包含包名)。
Spring Boot:
1 | # 实体对象的扫描包 |
Spring MVC:
1 | <!--这里使用MP提供的sqlSessionFactory,完成了Spring与MP的整合--> |
4.2 进阶配置
本部分(Configuration)的配置大都为 MyBatis 原生支持的配置,这意味着您可以通过 MyBatis XML 配置文件的形式进行配置。
4.2.1 mapUnderscoreToCamelCase
类型: boolean
默认值: true
是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN(下划线命名) 到经典 Java 属性名 aColumn(驼峰命名) 的类似映射。
注意:
此属性在 MyBatis 中原默认值为 false,在 MyBatis-Plus 中,此属性也将用于生成最终的 SQL 的 select body
如果您的数据库命名符合规则无需使用 @TableField 注解指定数据库字段名
1 | # 关闭自动驼峰映射,该参数不能和mybatis-plus.config-location同时存在 |
4.2.2 cacheEnabled
类型: boolean
默认值: true
全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存,默认为 true。
1 | # 禁用缓存 |
4.3 DB 策略配置
4.3.1 idType
类型: com.baomidou.mybatisplus.annotation.IdType
默认值: ID_WORKER
全局默认主键类型,设置后,即可省略实体对象中的@TableId(type = IdType.AUTO)配置。
SpringBoot:
1 | # 全局的id生成策略 |
SpringMVC:
1 | <!--这里使用MP提供的sqlSessionFactory,完成了Spring与MP的整合--> |
4.3.2 tablePrefix
类型: String
默认值: null
表名前缀,全局配置后可省略 @TableName()配置。
SpringBoot:
1 | # 全局的表名的前缀 |
SpringMVC:
1 | <!--这里使用MP提供的sqlSessionFactory,完成了Spring与MP的整合--> |
5. 条件构造器
在MP中,Wrapper接口的实现类关系如下:
可以看到, AbstractWrapper和AbstractChainWrapper是重点实现,接下来我们重点学习AbstractWrapper以及其子类。
说明:
QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类 用于生成 sql的 where 条件, entity 属性也用于生成 sql 的 where 条件 注意: entity 生成的 where 条件与 使用各个 api 生成的 where 条件没有任何关联行为
官网文档地址: https://mybatis.plus/guide/wrapper.html
5.1 allEq
1 | allEq (Map<R, V> params) |
全部eq(或个别isNull )
个别参数说明: params : key 为数据库字段名, value 为字段值 null2IsNull :
为 true 则在 map 的 value 为null 时调用 isNull 方法,为 false 时则忽略 value 为 null 的
例 1:
allEq({id:1,name:" 老王",age:null}) ---> id = 1 and name = ' 老王' and age is null
例 2:allEq({id:1,name:" 老王",age:null}, false) ---> id = 1 and name = ' 老王'
1 | allEq (BiPredicate<R, V> filter, Map<R, V> params) |
个别参数说明: filter : 过滤函数,是否允许字段传入比对条件中 params 与 null2IsNull : 同上
例 1: allEq((k,v) -> k.indexOf(“a”) > 0, {id:1,name:”老王”,age:null}) —> name = ‘老王’ and age is null
例 2: allEq((k,v) -> k.indexOf(“a”) > 0, {id:1,name:”老王”,age:null}, false) —> name =’老王’
1 | /** |
5.2 基本比较操作
操作 | 说明 |
---|---|
eq | 等于 = |
ne | 不等于 <> |
gt | 大于 > |
ge | 大于等于 >= |
lt | 小于 < |
le | 小于等于 <= |
between | BETWEEN 值1 AND 值2 |
notBetween | NOT BETWEEN 值1 AND 值2 |
in | 字段 IN (value.get(0), value.get(1), …) |
notIn | 字段 NOT IN (v0, v1, …) |
1 | /** |
5.3 模糊查询
操作 | 说明 |
---|---|
like | LIKE ‘% 值%’ 例 : like(“name”, “ 王”) —> name like ‘% 王%’ |
notLike | NOT LIKE ‘% 值%’ 例 : notLike(“name”, “ 王”) —> name not like ‘% 王%’ |
likeLeft | LIKE ‘% 值’ 例 : likeLeft(“name”, “ 王”) —> name like ‘% 王’ |
likeRight | LIKE ‘ 值%’ 例 : likeRight(“name”, “ 王”) —> name like ‘ 王%’ |
1 | /** |
5.4 排序
操作 | 说明 |
---|---|
orderBy | 排序: ORDER BY 字段, … 例 : orderBy(true, true, “id”, “name”) —> order by id ASC,name ASC |
orderByAsc | 排序: ORDER BY 字段, … ASC 例 : orderByAsc(“id”, “name”) —> order by id ASC,name ASC |
orderByDesc | 排序: ORDER BY 字段, … DESC 例 : orderByDesc(“id”, “name”) —> order by id DESC,name DESC |
1 | /** |
5.5 逻辑查询
操作 | 说明 |
---|---|
or | 拼接 OR 主动调用 or 表示紧接着下一个方法不是用 and 连接!(不调用 or 则默认为使用 and 连接) |
and | AND 嵌套 例 : and(i -> i.eq(“name”, “李白”).ne(“status”, “活着”)) —> and (name = ‘李白’ and status<> ‘活着’) |
1 | /** |
2.6 select
在MP查询中,默认查询所有的字段,如果有需要也可以通过select方法进行指定字段。
1 | /** |
-------------本文结束感谢您的阅读-------------
本文标题: Mybatis-Plus(一)
本文链接: https://wgy1993.gitee.io/archives/b19585ec.html
版权声明: 本作品采用 CC BY-NC-SA 4.0 进行许可。转载请注明出处!