springboot具体集成mybatis-plus可以查看:
springBoot 使用 mybatis-plus 插件 实现分页
mybatis-plus
1、官方文档
https://baomidou.com/guide/sequence.html#spring-boot
2、MyBatis Plus 介绍
MyBatis-plus 是国内人员开发的 MyBatis 增强工具,在 MyBatis 的基础上只做增强不做改变,引入 Mybatis-Plus 不会对现有的 Mybatis 构架产生任何影响,而且 MyBatis-plus 支持所有 Mybatis 原生的特性,为简化开发、提高效率而生。
3、MyBatis Plus 优点
3.1、依赖少:仅仅依赖 Mybatis 以及 Mybatis-Spring 。
3.2、损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作 。
3.3、预防Sql注入:内置 Sql 注入剥离器,有效预防Sql注入攻击 。
3.4、通用CRUD操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作。
3.5、内置分页插件:基于 Mybatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通List查询。
4、主要功能
MyBatis Plus 的核心功能有:
4.1、条件构造器
4.2、通用的 CRUD接口
4.3、分页插件
4.4、代码生成器
4.5、自定义ID生成器
4.6、Sequence主键
5、条件构造器
5.1、三个绿色父类就不讲了,主要介绍以下四个:
-
LambdaQueryWrapper :Lambda形式的查询Wrapper。
LambdaQueryWrapper<PressInfoEntity> lambdaQueryWrapper = new QueryWrapper<>().lambda(); LambdaQueryWrapper<PressInfoEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
-
LambdaUpdateWrapper :Lambda 形式的更新Wrapper。
LambdaUpdateWrapper<PressInfoEntity> updateWrapper = new UpdateWrapper<>().lambda() LambdaUpdateWrapper<PressInfoEntity> updateWrapper = new LambdaUpdateWrapper();
-
QueryWrapper :继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件及 LambdaQueryWrapper, 可以通过 new QueryWrapper().lambda() 方法获取。
-
UpdateWrapper : 继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件及 LambdaUpdateWrapper, 可以通过 new UpdateWrapper().lambda() 方法获取。
5.2、使用方法
5.3、注意点
1、对于上述存在sql注入风险的方法,建议能不用就不用。如果要用的话,必须确保里面的参数不存在sql注入问题。
2、单表操作的时候优先使用LambdaQueryWrapper ,因为QueryWrapper与表字段名强绑,如果修改表字段,n个方法使用这个条件,改动的地方会很多
QueryWrapper<PressInfoEntity> queryWrapper = new QueryWrapper<>()
.like("short_press","版");
LambdaQueryWrapper<PressInfoEntity> lambdaQueryWrapper = new QueryWrapper<>()
.lambda()
.like(PressInfoEntity::getShortPress,"版");
6、通用CRUD(版本不同,通用方法会有差异,这里以3.3.2为例)
PressInfoEntity.java实体类
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName(value="t_press_info")
public class PressInfoEntity {
@TableId
private int id;
@TableField(value = "short_press")
private String shortPress;
@TableField(value = "press")
private String press;
@TableField(value = "create_time")
private Date createTime;
@TableField(value = "update_time")
private Date updateTime;
// 表示当前字段不存在t_press_info表中
@TableField(value = "name" ,exist = false)
private String name;
}
6.1、新增 int insert(T entity);
int insert(T entity);
例子:
PressInfoEntity pressInfoEntity = PressInfoEntity.builder()
.shortPress("ces")
.press("c")
.createTime(new Date())
.build();
int flag= pressInfoMapper.insert(pressInfoEntity);
6.2、删除
int deleteById(Serializable id);
int deleteByMap(@Param("cm") Map<String, Object> columnMap);
int delete(@Param("ew") Wrapper<T> wrapper);
int deleteBatchIds(@Param("coll") Collection<? extends Serializable> idList);
例子:以下方法按查询删除
LambdaQueryWrapper<PressInfoEntity> wrapper=new LambdaQueryWrapper().eq(PressInfoEntity::getId,id);
pressInfoMapper.delete(wrapper);
6.3、修改
int updateById(@Param("et") T entity);
int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper);
例子:
PressInfoEntity pressInfoEntity = PressInfoEntity.builder().id(id).press("我也被修改了!").build();
pressInfoMapper.updateById(pressInfoEntity);
#LambdaUpdateWrapper 用于生成where条件,定位哪些数据需要修改,PressInfoEntity才是具体修改的内容
LambdaUpdateWrapper<PressInfoEntity> updateWrapper = new LambdaUpdateWrapper<>().eq(PressInfoEntity::getId,id);
PressInfoEntity pressInfoEntity = PressInfoEntity.builder().press("我被修改了!").build();
pressInfoMapper.update(pressInfoEntity,updateWrapper);
#sql: UPDATE t_press_info SET press=? WHERE (id = ?)
#如果只是修改单独个一两个值可以直接将第一个条件传null
LambdaUpdateWrapper<PressInfoEntity> updateWrapper = new LambdaUpdateWrapper<>()
.set(PressInfoEntity::getShortPress,"我被修改了")
.eq(PressInfoEntity::getId,id);
pressInfoMapper.update(null,updateWrapper);
6.4、查询
T selectById(Serializable id);
List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> idList);
List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);
T selectOne(@Param("ew") Wrapper<T> queryWrapper);
Integer selectCount(@Param("ew") Wrapper<T> queryWrapper);
List<T> selectList(@Param("ew") Wrapper<T> queryWrapper);
List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> queryWrapper);
List<Object> selectObjs(@Param("ew") Wrapper<T> queryWrapper);
例子:
List<Integer> idList= Arrays.asList(2,3);
List<PressInfoEntity> list=pressInfoMapper.selectBatchIds(idList);
LambdaQueryWrapper<PressInfoEntity> queryWrapper = new LambdaQueryWrapper<()
.like(PressInfoEntity::getShortPress,shortPress);
List<PressInfoEntity> list= pressInfoMapper.selectList(queryWrapper);
6.5、分页查询(放到分页插件内细说)
<E extends IPage<T>> E selectPage(E page, @Param("ew") Wrapper<T> queryWrapper);
<E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param("ew") Wrapper<T> queryWrapper);
6.6、QuerWapper使用 FIND_IN_SET
SELECT
id,
FROM
xxxxx
WHERE
(
grade_id = ?
AND semester_id = ?
AND subject_id = ?
AND staged_type = ?
AND province_id = ?
AND FIND_IN_SET ( '340800', city_id )
AND source_type IN ( ?,? )
AND test_online = ?
)
wrapper.apply(examinationPaperQueryVO.getCityId() != null, "FIND_IN_SET ('" + examinationPaperQueryVO.getCityId() + "',city_id)");
6.7、MybatisPlus结合groupby实现分组和Count
wrapper.groupBy(ExaminationPaperRelevancePO::getSchoolId);
实体类添加字段
注意:添加count(1) 之后,所有默认方法执行的sql都会加上它,统计数量,慎用
如果非得用,尽可能所有查询接口都根据某个唯一值groupBy一下
7、分页插件
7.1、新建MybatisPluConfig.java
@Configuration
@MapperScan("xxxx")
public class MybatisPluConfig {
/**
* mybatis-plus分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
return paginationInterceptor;
}
}
7.2、只需配置好分页拦截就可以直接使用
LambdaQueryWrapper<PressInfoEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>()
.like(PressInfoEntity::getShortPress,shortPress);
Page<PressInfoEntity> page=new Page<>(pageNo,pageSize);
IPage<PressInfoEntity> iPage= pressInfoMapper.selectPage(page,lambdaQueryWrapper);
#执行两条sql
#统计总数
SELECT COUNT(1) FROM t_press_info WHERE (short_press LIKE ?)
#分页查询
SELECT id,short_press,press,create_time,update_time FROM t_press_info WHERE (short_press LIKE ?) LIMIT ?,?
7.3、执行结果
{
"records": [
{
"id": 1,
"shortPress": "北京版",
"name": null,
"press": "北京出版社",
"createTime": null,
"updateTime": null
},
......
],
"total": 78,
"size": 3,
"current": 1,
"orders": [],
"optimizeCountSql": true,
"hitCount": false,
"searchCount": true,
"pages": 26
}
7.4、自定义多表关联分页查询
使用LambdaQueryWrapper
LambdaQueryWrapper<PressInfoEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>()
.like(PressInfoEntity::getShortPress,"版")
.like(PressInfoEntity::getName,"测试");
IPage<PressInfoEntity> iPage= pressInfoService.selectPageByPressLambda(page,lambdaQueryWrapper);
抛出异常,9.1会说明原因。
如果去掉 .like(PressInfoEntity::getName,"测试");可以正常执行。
使用QueryWrapper
QueryWrapper<PressInfoEntity> queryWrapper = new QueryWrapper<PressInfoEntity>();
queryWrapper.like("t.short_press","版");
queryWrapper.like("t1.name","测试");
IPage<PressInfoEntity> iPage= pressInfoService.selectPageByPressWrapper(page,queryWrapper);
推荐常规写法
PressInfoEntity pressInfoEntity = PressInfoEntity.builder().press(press).build();
Page<PressInfoEntity> page=new Page<>(1,5);
IPage<PressInfoEntity> iPage= pressInfoService.selectPageByEntity(page,pressInfoEntity);
#sql和mybatis一样就好
select t.*,t1.name from t_press_info t
left join t_press t1 on t.id=t1.press_info_id
<where> t.short_press like CONCAT('%',#{et.shortPress},'%') </where>
xml中要有相应的方法
<select id="selectPageByEntity" parameterType="com.test.mybatisplus.entity.PressInfoEntity" resultType="com.test.mybatisplus.entity.PressInfoEntity">
select t.*,t1.name from t_press_info t
left join t_press t1 on t.id=t1.press_info_id
<where> t.short_press like CONCAT('%',#{et.shortPress},'%') </where>
</select>
9、注意点
9.1、优先使用LambdaQueryWrapper ,QueryWrapper与表字段名强绑,如果修改表字段,改动的地方会很多
QueryWrapper<PressInfoEntity> queryWrapper = new QueryWrapper<PressInfoEntity>();
queryWrapper.like("short_press","版");
LambdaQueryWrapper<PressInfoEntity> lambdaQueryWrapper = new QueryWrapper<PressInfoEntity>()
.lambda()
.like(PressInfoEntity::getShortPress,"版")
缺点:如果自定义sql多表关联查询无法使用LambdaQueryWrapper,这种时候只能用其他方式
LambdaQueryWrapper<PressInfoEntity> queryWrapper = new QueryWrapper<>().lambda();
queryWrapper.like(PressInfoEntity::getShortPress,"版");
//使用非当前表内字段做查询
queryWrapper.like(PressInfoEntity::getName,"测试");
异常:can not find lambda cache for this property [name] of entity[com.test.mybatisplus.entity.PressInfoEntity]
原因:lambda cache 在初始化缓存数据的时候跟t_press_info强相关,name不在当前表中,所以获取的时候导致异常。
9.2、分页插件也执行了两条sql,源码里可以看到,如果isSearchCount=true则执行 queryTotal
SELECT COUNT(1) FROM t_press_info WHERE (short_press LIKE ?)
select * from t_press_info WHERE (short_press LIKE ?) ORDER BY id DESC LIMIT ?,?