1. 前言
MySQL一对多的数据分页是非常常见的需求,比如我们要查询商品和商品的图片信息。但是很多人会在这里遇到分页的误区,得到不正确的结果。今天就来分析并解决这个问题。
2. 问题分析
我们先创建一个简单商品表和对应的商品图片关系表,它们之间是一对多的关系:
然后我分别写入了一些商品和这些商品对应的图片,通过下面的左连接查询可以看出它们之间具有明显的一对多关系:
SELECTP.PRODUCT_ID, P.PROD_NAME, PI.IMAGE_URL
FROM PRODUCT_INFO P
LEFTJOINPRODUCT_IMAGEPI
ONP.PRODUCT_ID = PI.PRODUCT_ID
按照传统的思维我们的分页语句会这么写:
SELECT P.PRODUCT_ID, P.PROD_NAME,PI.IMAGE_URL
FROM PRODUCT_INFO P
LEFT JOIN PRODUCT_IMAGE PI
ON P.PRODUCT_ID = PI.PRODUCT_ID
LIMIT #{current},#{size}
当我按照预想传入了(0,2)想拿到前两个产品的数据,结果并不是我期望的:
2020-06-2123:35:54.515DEBUG10980---[main]c.f.m.mappers.ProductInfoMapper.page :==>Preparing:SELECTP.PRODUCT_ID,P.PROD_NAME,PI.IMAGE_URLFROMPRODUCT_INFOPLEFTJOINPRODUCT_IMAGEPIONP.PRODUCT_ID=PI.PRODUCT_IDlimit?,?
2020-06-2123:35:54.541DEBUG10980---[main]c.f.m.mappers.ProductInfoMapper.page :==>Parameters:0(Long),2(Long)
2020-06-2123:35:54.565DEBUG10980---[main]c.f.m.mappers.ProductInfoMapper.page :<==Total:2
page=[ProductDTO{productId=1,prodName='杯子',imageUrls=[http://asset.felord.cn/cup1.png,http://asset.felord.cn/cup2.png]}]
我期望的两条数据是杯子和笔记本,但是结果却只有一条。原来当一对多映射时结果集会按照多的一侧进行输出(期望4条数据,实际上会有7条),而前两条展示的只会是杯子的数据(如上图),合并后就只有一条结果了,这样分页就对不上了。那么如何才能达到我们期望的分页效果呢?
3. 正确的方式
正确的思路是应该先对主表进行分页,再关联从表进行查询。
抛开框架,我们的SQL应该先对产品表进行分页查询然后再做关联图片表进行查询:
SELECTP.PRODUCT_ID, P.PROD_NAME, PI.IMAGE_URL
FROM (SELECTPRODUCT_ID, PROD_NAME
FROMPRODUCT_INFO
LIMIT#{current},#{size}) P
LEFT JOIN PRODUCT_IMAGE PI
ON P.PRODUCT_ID = PI.PRODUCT_ID
这种写法的好处就是通用性强一些。但是MyBatis提供了一个相对优雅的路子,思路依然是开头所说的思路。只不过我们需要改造上面的Mybatis XML配置:
<!-- 利用 collection 标签提供的 select 特性 和 column -->
<!-- 先查询主表的分页数据 -->
SELECT PRODUCT_ID, PROD_NAME
FROM PRODUCT_INFO
LIMIT #{current},#{size}
<!--根据productId 查询对应的图片-->
SELECT IMAGE_URL
FROM PRODUCT_IMAGE
WHERE PRODUCT_ID = #{productId}
4. 总结
大部分情况下分页是很容易的,但是一对多还是有一些小小的陷阱的。一旦我们了解了其中的机制,也并不难解决。当然如果你有更好的解决方案可以留言讨论,集思广益。多多关注小编,获取更多开发技巧。
为了给在工作和技术上遇到瓶颈的同学找到发展方向,今天特意给大家带来一位大神:
马士兵老师
清华大学毕业,历任程序员、Team Leader、Project Manager、CTO等职位,有过十几个大型项目的开发经验。看到特别复杂的技术就来气,不用简单的语言把它讲出来就不爽!
马士兵老师,推动Java生根中国,推动大数据生根中国,推动AI生根中国,视频课程下载次数累计数万次。
本月25-26号两节课!马老师来给你讲解横扫一些关于多线程的问题,吊打所有敢于提问高并发问题的面试官!
免费!免费! 免费哈!重要的事情说三遍
两天授课内容
第一天内容(预习资料找我提前领取)
第二天内容:
马老师的讲课质量怎么样?(话不多说看图)
文章到这就结束了图就截取这两张吧 ,就不一一展示了,想了解更多和想跟着马老师学习这节课内容的同学们关注小编,转发收藏文章,添加v:bjmsb07 既可以免费学习并提前领取预习资料。抓紧时间!错过来就没有了哈!