SpringBoot+MyBatis——基于PageHelper插件分页操作过程
中全注解实。。。
在利⽤SpringBoot集成MyBatis实现简单的业务操作时,遇到了⼀个坑,记录⼀下。
⼀般来讲,实现多条件模糊查询的逻辑为:前端页⾯输⼊各项参数,提交查询请求时,参数通过RUL(或者请求体)传输到后端。后端提取出相关参数,注⼊⾄sql语句,实现多条件模糊查询。
Service层相关代码(本⽂省略Controller层代码)
/**
* 分页查询(基于此实现多条件模糊查询)
*/
@Override
public PageInfo<ProductInfo> splitPageForPageInfo(int pageNum, int pageSize, ProductInfo productInfo) {
PageHelper.startPage(pageNum, pageSize);
List<ProductInfo> productInfoList = productDao.selectAll(productInfo);
//PageHelper相关配置已经在yml⽂件中声明,项⽬加载时会⽣成bean放⼊到Spring容器中
//原sql语句后⾯会⾃动添加Limit
PageInfo<ProductInfo> pageInfo = new PageInfo<>(productInfoList);
return pageInfo;
}
刚开始本⼈的Dao层代码如下所⽰
@Select("<script>"
+"select * from product_info"
+ "<where>"
+ "<if test='typeId !=null'> and type_id like CONCAT('%',#{typeId},'%')</if>"
+ "<if test='pName !=null'> and p_name like CONCAT('%',#{pName},'%')</if>"
+ "<if test='pContent !=null'> and p_content like CONCAT('%',#{pContent},'%')</if>"
+ "<if test='pNumber !=null'> and p_number like CONCAT('%',#{pNumber},'%')</if>"
+ "<if test='pPrice !=null'> and p_price like CONCAT('%',#{pPrice},'%')</if>"
+ "</where>"
+"</script>"
)
List<ProductInfo> selectAll(ProductInfo productInfo);
注意到此处的<if>标签中,只包含了各个属性为null的情况,⽽忽略了它们为空串的情形,这个⼩细节将会导致后续页⾯⽆法正常显⽰数据,并且我们很难查出错误所在。⽐如本⼈在测试类中调试Service层splitPageForPageInfo()⽅法,代码与运⾏结果如下:
@Test
void testSplitPageForPageInfo() {
ProductInfo productInfo = new ProductInfo();
productInfo.setTypeId("电脑");
PageInfo pageInfo = productService.splitPageForPageInfo(1, 3, productInfo);
List<ProductInfo> productInfoList = List();
for (ProductInfo p : productInfoList) {
System.out.println(p);
}
}
2021-12-30 09:30:23.273 DEBUG 11764 --- [ main] c.wangjf.dao.ProductDao.selectAll_COUNT : ==> Preparing: SELECT count(0) FROM product_
2021-12-30 09:30:23.299 DEBUG 11764 --- [ main] c.wangjf.dao.ProductDao.selectAll_COUNT : ==> Parameters: 电脑(String)
2021-12-30 09:30:23.319 DEBUG 11764 --- [ main] c.wangjf.dao.ProductDao.selectAll_COUNT : <== Total: 1
2021-12-30 09:30:23.322 DEBUG 11764 --- [ main] com.wangjf.dao.ProductDao.selectAll : ==> Preparing: select * from product_info WHERE type_id lik 2021-12-30 09:30:23.323 DEBUG 11764 --- [ main] com.wangjf.dao.ProductDao.selectAll : ==> Parameters: 电脑(String), 3(Integer)
2021-12-30 09:30:23.326 DEBUG 11764 --- [ main] com.wangjf.dao.ProductDao.selectAll : <== Total: 2
ProductInfo(pId=4, pName=联想⼩新, pContent=dddd, pPrice=8000.0, pNumber=1, typeId=电脑)
ProductInfo(pId=13, pName=外星⼈, pContent=⽔, pPrice=10999.0, pNumber=1, typeId=电脑)
通过MyBatis⽇志输出可以看到,此代码逻辑下sql语句的运⾏顺序为:⾸先查询出type_id字段中含有''电脑"这个字符串的所有数据(⼤家
⾃动忽略此处的数据名称和内容...此表是俺从上⼀个项⽬中随便捡来的...),再利⽤Limit语句分页。可以看到查询结果是正确的
⽽当我们将productInfo对象赋为null,理论上sql语句执⾏顺序为:因⽆条件匹配,直接在原sql语句后⾯加上Limit实现分页。从运⾏⽇志
可以看出执⾏顺序也确实如此:
@Test
void testSplitPageForPageInfo() {
//ProductInfo productInfo = new ProductInfo();
//productInfo.setTypeId("电脑");
PageInfo pageInfo = productService.splitPageForPageInfo(1, 3,null);
List<ProductInfo> productInfoList = List();
for (ProductInfo p : productInfoList) {
System.out.println(p);
}
}springboot是啥
2021-12-30 09:31:56.297 DEBUG 6404 --- [ main] c.wangjf.dao.ProductDao.selectAll_COUNT : ==> Preparing: SELECT count(0) FROM product_i
2021-12-30 09:31:56.324 DEBUG 6404 --- [ main] c.wangjf.dao.ProductDao.selectAll_COUNT : ==> Parameters:
2021-12-30 09:31:56.341 DEBUG 6404 --- [ main] c.wangjf.dao.ProductDao.selectAll_COUNT : <== Total: 1
2021-12-30 09:31:56.343 DEBUG 6404 --- [ main] com.wangjf.dao.ProductDao.selectAll : ==> Preparing: select * from product_info LIMIT ?
2021-12-30 09:31:56.344 DEBUG 6404 --- [ main] com.wangjf.dao.ProductDao.selectAll : ==> Parameters: 3(Integer)
2021-12-30 09:31:56.346 DEBUG 6404 --- [ main] com.wangjf.dao.ProductDao.selectAll : <== Total: 3
ProductInfo(pId=1, pName=iphone14, pContent=128GB, pPrice=5999.0, pNumber=1, typeId=2)
ProductInfo(pId=2, pName=iphone15, pContent=256GB, pPrice=6799.0, pNumber=2, typeId=1)
ProductInfo(pId=3, pName=专⽤座机, pContent=null, pPrice=null, pNumber=null, typeId=⼿机)
为确保万⽆⼀失,本⼈还⽤Postman进⾏了测试
1.查询全部
2.按照pageNum=1,pageSize=3分页查询
3.基于条件typeId="电脑"进⾏模糊查询
但是当我将项⽬运⾏-->打开⽹页--->刷新.. 竟然GG了..
乍⼀看,似乎没啥问题,但是仔细⼀看.. 竟然漏掉了字段属性存在空值的⼀条数据(通过控制台打印的消息也可以看到total=6)
怎么可以容忍这样的事情发⽣?!
经过漫长的寻觅.. (不再赘述本⼈的痛苦遭遇),终于发现原因为:在<if>标签中没有考虑数据为空串的情况.... 修改Dao层代码如下:
@Select("<script>"
+"select * from product_info"
+ "<where>"
+ "<if test='typeId !=null and typeId != \"\"'> and type_id like CONCAT('%',#{typeId},'%')</if>"
+ "<if test='pName !=null and pName != \"\"'> and p_name like CONCAT('%',#{pName},'%')</if>"
+ "<if test='pContent !=null and pContent != \"\"'> and p_content like CONCAT('%',#{pContent},'%')</if>"
+ "<if test='pNumber !=null and pNumber != \"\"'> and p_number like CONCAT('%',#{pNumber},'%')</if>"
+ "<if test='pPrice !=null and pPrice != \"\"'> and p_price like CONCAT('%',#{pPrice},'%')</if>"
+ "</where>"
+"</script>"
)
List<ProductInfo> selectAll(ProductInfo productInfo);
最终可得正确⽹页显⽰(控制台输出total=7):
多条件模糊查询功能也正常
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论