MyBatis怎样实现MySQL动态分页

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis怎样实现MySQL动态分页相关的知识,希望对你有一定的参考价值。

一、mysql 使用limit 子句来实现数据库的物理分页,limit 子句接受 一个或两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数量。在mybatis 中,只需要在相 应的查询语句后,加上limit 子句,即可实现物理分页。如下,以 一个只有字段id,name,age 的表为例。该配置会根据传入的 hashmap,如果含有键start 和键end,那么即通过mybatis 强大的 动态sql,生成含有mysql 分页的sql语句。 select * from users limit #start,#end

二、mybaits 简介
mybatis,前称ibatis,后改名为mybatis,截止本文成文,最新 版本是3.0.6。它和hibernate 是java世界使用最多的两种orm 框 架。hibernate 理念最为先进,完全实现面向对象的数据库编程,不需要掌握sql 语句,即可实现数据库操作,能够节省开发人员编 写大量sql语句的时间。但是,hibernate 在处理多表关联时,可 能会出现n+1 问题,性能会有较大影响,要解决性能问题,需要较 深的hibernate 知识和项目经验。mybatis 需要自己写sql 语句, 开发效率不如hibernate,很难做到底层多数据库的通用。但对程 序员来说有更高的可控性,可以更容易的对sql 语句进行优化,提 高效率。
在开发中直接使用jdbc 一个非常普遍的问题就是动态sql。如果 参数值、参数本身和数据列都是动态sql,通常的解决方法就是写很多if-else 条件语句和字符串连接。而mybatis 通过ognl 提供 了一套非常清晰的方法来解决动态sql 的问题。
参考技术A 第一种:Select * from user limit #p1,#p2-1
用这种方式是不行的,因为在MySQL中limit后面是不允许接表达式的;

在网上查了下MySQL还有一种动态分页,用MyBatis试了下报语法错误,直接在MySQL中运行是可以的,如下:
<select id="findUsers" resultType="sun.bean.dome.entity.User" statementType="PREPARED">
PREPARE PAGE FROM 'SELECT * FROM USER LIMIT ?,?';
SET @START=1;
SET @SIZE=3+1;
EXECUTE PAGE USING @START,@SIZE;
</select>

其实只想Limit后面的分页参数,是根据传递过来的参数动态运算出来的,求助~!
(数据库迁移Oracle到MySQL,所需分页参数不同)
参考技术B 1、亲Mybatis是自己写Sql语句啊,和Hibernate不一样。
2、如何知道上面的,你还要知道MySql有一个分页语句叫limit,如:limit(1,10);前面一个参数是起始未知,后面一个是查询多少个。
3、Oracle的分页方法是嵌套子查询,需要用到rownum这个属性
Sql Server是Top。

分页例子:
Oracle select * from (select emp.*,rownum rn from emp where rownum<9) where rn>3;
MySql select * from emp limit startIndex,maxNum本回答被提问者和网友采纳
参考技术C 里面有现成的方法,调用就好

springboot2.x+MyBatis-Plus+mysql5.7 动态拼接sql语句 分页查询 自定义sql 查询条件 分组 排序

在使用srpingboot2.x+mybatis-plus框架是遇到特殊需求时研究mybatis-plus的条件构造器动态拼接sql查询,这个查询接口涉及到了自定义sql动态拼接sql分页求和分组排序。

可以直接看业务实现方法


首先说一下接口的需求:

入参JSON:

 1 {
 2     "from": "2020-5-29",
 3     "limit": 10,
 4     "offset": 0,
 5     "order": "hitCount",
 6     "page": 1,
 7     "search": "",
 8     "sort": "desc",
 9     "sortDirection": "",
10     "to": "2020-6-10"
11 }

入参注释说明:

{
    "from": "开始查询时间",
    "limit": 条数,
    "offset": 0,
    "order": "需要排序的字段",
    "page": 页码,
    "search": "查询条件",
    "sort": "排序规则",
    "sortDirection": "",
    "to": "结束查询时间"
}

然后先写接口实现:

1     @PostMapping("categoryList")
2     public R getCategoryList(@Validated @RequestBody QaDetailSearchVo vo){
3         RobotPage pageHelper = new RobotPage(vo.getPage(),vo.getLimit());
4         return R.ok(iStatQaService.findQaStatCategory(pageHelper, vo));
5     }

解释:POST请求,R 是自定义的返回类型,RobotPage是为了实现一些特殊返回值 继承于mybatsi-plus分页的Ipage:

1 public class RobotPage<T> extends Page<T> implements Serializable {}

重点是业务实现类和mapper层:

对于一般的查询mybatis-plus的条件构造器已经可以满足了,例如:

1 SysUser sysUser = baseMapper.selectOne(Wrappers.<SysUser>lambdaQuery()
2                 .select(SysUser::getUserId, SysUser::getUsername, SysUser::getPhone, SysUser::getEmail, SysUser::getPassword, SysUser::getDeptId, SysUser::getJobId, SysUser::getAvatar)
3                 .eq(SysUser::getUsername, username));

但是对于一些需要复杂的或者多表的操作就需要自定义sql语句了,示例:

首先是mapper自定义分页查询接口:

1 @Select("SELECT s.category_id as id, s.category_name as category, SUM(s.hit_count) as hitCount, SUM(s.solve_count) as resolvedCount, SUM(s.not_solve_count) as unresolvedCount " +
2             "FROM core_stat_qa as s ${ew.customSqlSegment}")
3     IPage<QaDetailCategoryListVo> findCategoryListByParams(IPage<QaDetailCategoryListVo> page, @Param(Constants.WRAPPER) QueryWrapper<StatQa> wrappers);

这部分官网给的有示例:https://mybatis.plus/guide/wrapper.html#%E4%BD%BF%E7%94%A8-wrapper-%E8%87%AA%E5%AE%9A%E4%B9%89sql

业务接口不用看 直接是实现类:

 1 @Override
 2     public Grid findQaStatCategory(Page<QaDetailCategoryListVo> page, QaDetailSearchVo vo) {
 3         //声明返回
 4         Grid grid = new Grid();
 5         //组装查询语句
 6         QueryWrapper<StatQa> qaQueryWrapper = new QueryWrapper<>();
 7         //模糊查询
 8         qaQueryWrapper.like(StringUtils.isNotBlank(vo.getSearch()),"category_name",vo.getSearch());
 9         //where条件
10         qaQueryWrapper.ge("create_time", DateUtil.parse(vo.getFrom(),"yyyy-MM-dd"));
11         qaQueryWrapper.lt("create_time",DateUtil.parse(vo.getTo(), "yyyy-MM-dd"));
12         //分组
13         qaQueryWrapper.groupBy("category_id","category_name");
14         //排序
15         qaQueryWrapper.orderBy(true, !"desc".equals(vo.getSort()),vo.getOrder());
16         //调用自定义sql语句
17         IPage<QaDetailCategoryListVo> statQaIPage = baseMapper.findCategoryListByParams(page, qaQueryWrapper);
18         //抽取list
19         List<QaDetailCategoryListVo> statQaList = statQaIPage.getRecords();
20         grid.setList(statQaList);
21         grid.setTotal(statQaIPage.getTotal());
22         return grid;
23     }

需要解释的:

排序orderBy方法中的第一个true官网上也是给出解释的:表示该条件是否加入最后生成的sql中。

!"desc".equals(vo.getSort())  是排序规则 asc和desc

调用mapper自定义sql就是:
baseMapper.findCategoryListByParams(page, qaQueryWrapper);

接口完成。

以上是关于MyBatis怎样实现MySQL动态分页的主要内容,如果未能解决你的问题,请参考以下文章

mybatis 中怎样实现oracle分页语句

springboot2.x+MyBatis-Plus+mysql5.7 动态拼接sql语句 分页查询 自定义sql 查询条件 分组 排序

springboot2.x+MyBatis-Plus+mysql5.7 动态拼接sql语句 分页查询 自定义sql 查询条件 分组 排序

mybatis分页插件pagehelper

SpringBoot+MyBatis+Mysql+Durid实现动态多数据源

mybatic MapperScannerConfigurer的原理