Mybatis如何实现分页

本文介绍了Mybatis实现分页的三种方式:通过关键字limit、Interceptor Plugin拦截器以及PageHelper辅助类。Interceptor Plugin通过拦截特定方法并拼接SQL的limit实现分页,而PageHelper则更简单,只需在查询前调用startPage方法,它会自动转换SQL并获取总行数,提供高性能的分页功能。

Mybatis如何实现分页

关键字limit实现分页

Interceptor Plugin实现分页

首先定一个拦截器,拦截器会拦截所有以ByPage结尾的方法,然后拼接sql 语句的limit关键字实现分页

@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class MyPageInterceptor implements Interceptor {

    private int page;
    private int size;
    @SuppressWarnings("unused")
    private String dbType;

    @SuppressWarnings("unchecked")
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
        while (metaObject.hasGetter("h")) {
            Object object = metaObject.getValue("h");
            metaObject = SystemMetaObject.forObject(object);
        }
        while (metaObject.hasGetter("target")) {
            Object object = metaObject.getValue("target");
            metaObject = SystemMetaObject.forObject(object);
        }
        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
        String mapId = mappedStatement.getId();
        if (mapId.matches(".+ByPage$")) {
            ParameterHandler parameterHandler = (ParameterHandler) metaObject.getValue("delegate.parameterHandler");
            Map<String, Object> params = (Map<String, Object>) parameterHandler.getParameterObject();
            page = (int) params.get("page");
            size = (int) params.get("size");
            String sql = (String) metaObject.getValue("delegate.boundSql.sql");
            sql += " limit " + (page - 1) * size + "," + size;
            metaObject.setValue("delegate.boundSql.sql", sql);
        }
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        String limit = properties.getProperty("limit", "10");
        this.page = Integer.parseInt(limit);
        this.dbType = properties.getProperty("dbType", "mysql");
    }

}

修改controller的findByUserPager方法,拦截器已经自动帮我们算好了page和size的值

    public Pager<User> findByUserPager(int page, int size){
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("page", page);
        params.put("size", size);
        List<User> list = userMapper.findUserByPage(params);
        Pager<User> pager = new Pager<User>();
        pager.setData(list);
        pager.setTotal(userMapper.findUserCount());
        return pager;
    }

PageHelper实现分页

//第二种,Mapper接口方式的调用,推荐这种使用方式。
PageHelper.startPage(1, 10);
// Page<User> page = PageHelper.startPage(1, 10);
List<User> list = userMapper.selectIf(1);

//第三种,Mapper接口方式的调用,推荐这种使用方式。
PageHelper.offsetPage(1, 10);
List<User> list = userMapper.selectIf(1);

在你需要进行分页的 MyBatis 查询方法前调用 PageHelper.startPage 静态方法即可,紧跟在这个方法后的第一个MyBatis 查询方法会被进行分页。

分页原理:PageHelper.startPage会拦截下一个sql,也就是userMapper.selectIf(1)的SQL。并且根据当前数据库的语法,把这个SQL改造成一个高性能的分页SQL,同时还会查询该表的总行数,具体可以看SQL日志。

PageHelper.startPage和userMapper.selectIf(1)最好紧跟在一起,中间不要有别的逻辑,否则可能出BUG。
Page<User> page:相当于一个list集合,selectIf(1)方法查询完成后,会给page对象的相关参数赋值。

public PageInfo<User> testPage(User user, Pageable pageable) {
    int page = pageable.getPageNum();
    int size = pageable.getPageSize();

	//项目里自定义的pojo类
    User tempuser = new User();
    tempuser.setName(user.getName());
    //重点就是这句
    PageHelper.startPage(page, size);
    //这里调用的是mybatis的mapper
    List<Userl> tempusers = UserDao.selectByPage(tempuser);
    //用PageInfo包装了一下(官方推荐)
    return new PageInfo<>(tempusers);
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值