MyBatisPlus
1.简介
1.什么是Mybatis-plus?
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
2.开发环境准备
1.配置数据库环境,创建一张测试表
2.创建springboot项目,引入依赖
<!--mybatis plus 起步依赖--> |
---|
3.编写DataSource相关配置
spring: |
---|
4.编写实体类
@Data |
---|
1) @TableField("name") 指定映射关系。
- 实体类的属性名和数据库的字段名自动映射。
- 自动映射条件:名称一样,或者数据库字段使用_分割,实体类属性名使用驼峰名称
- 否则需要使用@TableField("name") 指定映射关系。
2)@TableField(exist = false) 忽略某个字段的查询和插入。
3) @TableId(type = IdType.AUTO)设置id生成策略:AUTO 数据库自增。
- AUTO 数据库ID自增,依赖于数据库。在插入操作生成SQL语句时,不会插入主键这一列
- NONE 未设置主键类型。用户输入,为空则会根据主键的全局策略自动生成
- INPUT 需要手动设置主键,若不设置。插入操作生成SQL语句时,主键这一列的值会是
null
- ID_WORKER(Long) 当实体类的主键属性为空时,才会自动填充
- ID_WORKER_STR(String) 当实体类的主键属性为空时,才会自动填充
- UUID 当实体类的主键属性为空时,才会自动填充,使用UUID
4)@TableLogic(value = "0", delval = "1")设置逻辑删除字段,并设置删除与未删的代表值
添加该注解之后:
- 删除转变为更新,调用mp提供的删除接口时,更新disable字段0->1
- 只对自动注入的SQL起效
- 查询时自动生成where disable=0查询
- 更新时自动生成where disable=0条件防止更新到已删除数据
- 自己写的删除接口依然为物理删除
不添加此注解时:
- mp提供的删除接口默认为物理删除
5.启动类增加 @MapperScan 注解,指定dao包的位置
@SpringBootApplication |
---|
3.Mapper 接口
编写dao
使用mp定义Mapper,需要让Mapper接口继承 BaseMapper接口。
@Mapper |
---|
1.增加
// 插入一条记录
int insert(T entity);
类型 |
参数名 |
描述 |
---|---|---|
T | entity | 实体对象 |
2.删除
// 根据 entity 条件,删除记录
int delete(Wrapper<T> wrapper);
// 删除(根据ID 批量删除)
int deleteBatchIds(Collection<? extends Serializable> idList);
// 根据 ID 删除
int deleteById(Serializable id);
// 根据 columnMap 条件,删除记录
int deleteByMap(Map<String, Object> columnMap);
类型 | 参数名 | 描述 |
---|---|---|
Wrapper<T> | wrapper | 实体对象封装操作类(可以为 null) |
Collection<? extends Serializable> | idList | 主键ID列表(不能为 null 以及 empty) |
Serializable | id | 主键ID |
Map<String, Object> | columnMap | 表字段 map 对象 |
3.修改
// 根据 whereWrapper 条件,更新记录
int update(Wrapper<T> updateWrapper);
// 根据 ID 修改
int updateById(T entity);
类型 | 参数名 | 描述 |
---|---|---|
T | entity | 实体对象 (set 条件值,可为 null) |
Wrapper<T> | updateWrapper | 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句) |
4.查询
// 根据 ID 查询
T selectById(Serializable id);
// 根据 entity 条件,查询一条记录
T selectOne(Wrapper<T> queryWrapper);
// 查询(根据ID 批量查询)
List<T> selectBatchIds(Collection<? extends Serializable> idList);
// 根据 entity 条件,查询全部记录
List<T> selectList(Wrapper<T> queryWrapper);
// 查询(根据 columnMap 条件)
List<T> selectByMap(Map<String, Object> columnMap);
// 根据 Wrapper 条件,查询全部记录,只展示查询的字段,不展示为null的字段
List<Map<String, Object>> selectMaps(Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
List<Object> selectObjs(Wrapper<T> queryWrapper);
// 根据 entity 条件,查询全部记录(并翻页)
IPage<T> selectPage(IPage<T> page, Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录(并翻页)
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询总记录数
Integer selectCount(Wrapper<T> queryWrapper);
类型 | 参数名 | 描述 |
---|---|---|
Serializable | id | 主键ID |
Wrapper<T> | queryWrapper | 实体对象封装操作类(可以为 null) |
Collection<? extends Serializable> | idList | 主键ID列表(不能为 null 以及 empty) |
Map<String, Object> | columnMap | 表字段 map 对象 |
IPage<T> | page | 分页查询条件(可以为 RowBounds.DEFAULT) |
条件构造器
AbstractWrapper是QueryWrapper和 UpdateWrapper的父类,用于生成 sql 的 where 条件
AbstractWrapper:
|
---|
-
LIKE '%值%'
- 例: like("name", "王")--->name like '%王%
|
---|
-
等于 =
-
例: eq("name", "老王")--->name = '老王'
|
---|
-
LIKE '%值'
-
例: likeLeft("name", "王")--->name like '%王'
|
---|
- LIKE '值%'
- 例: likeRight("name", "王")--->name like '王%'
|
---|
- 大于 >
- 例: gt("age", 18)--->age > 18
|
---|
-
大于等于 >=
-
例: ge("age", 18)--->age >= 18
|
---|
- 小于 <
- 例: lt("age", 18)--->age < 18
|
---|
- 小于等于 <=
- 例: le("age", 18)--->age <= 18
|
---|
- 字段 IS NULL
- 例: isNull("name")--->name is null
|
---|
- 字段 IS NOT NULL
- 例: isNotNull("name")--->name is not null
|
---|
- 字段 IN (value.get(0), value.get(1), ...)
- 例: in("age",{1,2,3})--->age in (1,2,3)
|
---|
- 排序:ORDER BY 字段, ...
- 例: orderBy(true, true, "id", "name")--->order by id ASC,name ASC
|
---|
- BETWEEN 值1 AND 值2
- 例: between("age", 18, 30)--->age between 18 and 30
|
---|
- NOT BETWEEN 值1 AND 值2
- 例: notBetween("age", 18, 30)--->age not between 18 and 30
|
---|
- 分组:GROUP BY 字段, ...
- 例: groupBy("id", "name")--->group by id,name
|
---|
- HAVING ( sql语句 )
- 例: having("sum(age) > 10")--->having sum(age) > 10
- 例: having("sum(age) > {0}", 11)--->having sum(age) > 11
|
---|
- 拼接 OR
- 主动调用or表示紧接着下一个方法不是用and连接!(不调用or则默认为使用and连接)
|
---|
- 该方法可用于数据库函数 动态入参的params对应前面的{index}部分.这样是不会有sql注入风险的,反之会有!
-
apply("date_format(dateColumn,'%Y-%m-%d') = {0}", "2008-08-08")--->date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
QueryWrapper:
|
---|
- 设置查询字段
- 例: select("id", "name", "age")->select id,name,age
UpdateWrapper:
|
---|
- SQL SET 字段
- 例: set("name", "wang")
- 例: set("name", "")--->数据库字段值变为空字符串
- 例: set("name", null)--->数据库字段值变为null
|
---|
- 设置 SET 部分 SQL
- 例: setSql("name = 'wang'")
4.Service接口
说明:
通用 Service CRUD 封装IService 接口,进一步封装 CRUD 采用 get 查询、单行 remove 删除、 list 查询集合、 page 分页, 前缀命名方式区分 Mapper 层避免混淆。
需要继承Service类
public interface UserInfoService extends IService<UserInfo> {} |
---|
建议如果存在自定义通用 Service 方法,请创建自己的 BaseService 继承 Mybatis-Plus 提供的基类
public interface UserInfoService extends BaseService<UserInfo> {} public interface BaseService extends IService<UserInfo> {} |
---|
接口介绍:
#Save
// 插入一条记录(选择字段,策略插入)
boolean save(T entity);
// 插入(批量)
boolean saveBatch(Collection<T> entityList);
类型 |
参数名 |
描述 |
---|---|---|
T | entity | 实体对象 |
Collection<T> | entityList | 实体对象集合 |
SaveOrUpdate
// 主键id存在更新记录,否则插入一条记录
boolean saveOrUpdate(T entity);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);
类型 | 参数名 | 描述 |
---|---|---|
T | entity | 实体对象 |
Collection<T> | entityList | 实体对象集合 |
int | batchSize | 插入批次数量 |
#Remove
// 根据 entity 条件,删除记录
boolean remove(Wrapper<T> queryWrapper);
// 根据 ID 删除
boolean removeById(Serializable id);
// 根据 columnMap 条件,删除记录
boolean removeByMap(Map<String, Object> columnMap);
// 删除(根据ID 批量删除)
boolean removeByIds(Collection<? extends Serializable> idList);
类型 | 参数名 | 描述 |
---|---|---|
Wrapper<T> | queryWrapper | 实体包装类 QueryWrapper |
Serializable | id | 主键ID |
Map<String, Object> | columnMap | 表字段 map 对象 |
Collection<? extends Serializable> | idList | 主键ID列表 |
#Update
// 根据 updateWrapper条件,更新记录
boolean update(T updateEntity, Wrapper<T> updateWrapper);
// 根据 ID 选择修改
boolean updateById(T entity);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);
类型 | 参数名 | 描述 |
---|---|---|
Wrapper<T> | updateWrapper | 实体对象封装操作类 UpdateWrapper |
T | entity | 实体对象 |
Collection<T> | entityList | 实体对象集合 |
int | batchSize | 更新批次数量 |
#Get
// 根据 ID 查询
T getById(Serializable id);
// 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常
T getOne(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
// 根据 Wrapper,查询一条记录
Map<String, Object> getMap(Wrapper<T> queryWrapper);
类型 | 参数名 | 描述 |
---|---|---|
Serializable | id | 主键ID |
Wrapper<T> | queryWrapper | 实体对象封装操作类 QueryWrapper |
boolean | throwEx | 有多个 result 是否抛出异常 |
T | entity | 实体对象 |
#List
// 查询所有
List<T> list();
// 查询列表
List<T> list(Wrapper<T> queryWrapper);
// 查询(根据ID 批量查询)
Collection<T> listByIds(Collection<? extends Serializable> idList);
// 查询(根据 columnMap 条件)
Collection<T> listByMap(Map<String, Object> columnMap);
// 查询所有列表,不显示为null的字段
List<Map<String, Object>> listMaps();
// 根据条件查询所有列表,不显示为null的字段
List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper);
// 查询全部记录,只显示第一个字段
List<Object> listObjs();
// 根据 Wrapper 条件,查询全部记录
List<Object> listObjs(Wrapper<T> queryWrapper);
类型 | 参数名 | 描述 |
---|---|---|
Wrapper<T> | queryWrapper | 实体对象封装操作类 QueryWrapper |
Collection<? extends Serializable> | idList | 主键ID列表 |
Map<?String, Object> | columnMap | 表字段 map 对象 |
#Count
// 查询总记录数
int count();
// 根据 Wrapper 条件,查询总记录数
int count(Wrapper<T> queryWrapper);
类型 |
参数名 |
描述 |
---|---|---|
Wrapper<T> | queryWrapper | 实体对象封装操作类 QueryWrapper |
5.分页插件
写mybatis-plus配置类,用来配置使用的数据库
@Configuration |
---|
写service,可以调用mp中service层提供的分页接口和Ipage插件进行分页。
// 无条件分页查询
IPage<T> page(IPage<T> page);
// 条件分页查询
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
// 无条件分页查询,不显示null字段
IPage<Map<String, Object>> pageMaps(IPage<T> page);
// 条件分页查询,不显示null字段
IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper);
类型 | 参数名 | 描述 |
---|---|---|
IPage<T> | page | 翻页对象 |
Wrapper<T> | queryWrapper | 实体对象封装操作类 QueryWrapper |
编码:
@Override |
---|
测试
所执行的sql
6.SQL分析
在MybatisPlusConfig当中添加配置代码,此配置可以显示SQ语句和运行时间
@Bean |
---|
测试
7.代码生成器
1.添加依赖
|
---|
2.添加模板依赖
MyBatis-Plus 支持 Velocity(默认)、Freemarker、Beetl,项目中使用的是Freemarker,我们以Freemarker为例。
<dependency> |
---|
3.编写配置类
设置存放路径,作者
GlobalConfig gc = new GlobalConfig(); |
---|
数据源配置
DataSourceConfig dsc = new DataSourceConfig(); |
---|
包配置
PackageConfig pc = new PackageConfig(); |
---|
其他配置
// 如果模板引擎是 freemarker |
---|
7.测试
执行main方法,输入模块名和表名:
成功生成代码
8.Demo
9.fir项目
1.fir-db
1.实体类添加注解,以MetricData为例,用于数据库表与实体类、字段与属性对应
@TableName("metric_data") |
---|
2.Mapper层继承BaseMapper,可以调用mp提供的API
public interface MetricDataRepository extends BaseRepository<MetricData, Long>{} public interface BaseRepository<T, ID extends Serializable> extends BaseMapper<T>() |
---|
3.Service层继承Iservice,可以调用mp提供的API
public interface MetricDataService extends BaseService<MetricData>{} public interface BaseService<T> extends IService<T>{} |
---|
4.使用了自定义通用Service类,定义了一些常用的方法,方便复用
public interface BaseService<T> extends IService<T> |
---|
5.MybatisPlusConfig中写了一些配置,用于配置分页插件和SQL分析插件
@Configuration |
---|
6.条件查询的构造方式
Controller层,attribute(字段)、operator(操作)、values(值)封装到Condition中,col(字段)、direction(方向)封装到Ordering中,然后把这些数据封装到SearchRequest中。
Service层,调用BaseService中的findBySearchRequest方法进行分页查询,迭代构造条件,最后返回SearchResult。
例:Controller层:封装Condition、Ordering、page、limit到SearchRequest,以searchRequest为参数调用service中的search()。
这里面封装数据的SearchRequest,代码如下图所示。
Service层:调用BaseService类中的findBySearchRequest方法用于分页查询。
返回结果SearchResult,代码如图所示。
BaseService中findBySearchRequest方法,主要用于分页,调用contructWrapper方法构造条件。
BaseService中contructWrapper方法用于迭代构造查询条件,调用addCondition方法。
addCondition方法:主要用于匹配操作名称和构造条件。
private QueryWrapper addCondition(String attribute, String operator, List<Object> valuesList, QueryWrapper queryWrapper) { |
---|
枚举类,用于选择对应的查询条件。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?