Mybatis的四种分页方式详解

Mybatis的四种分页方式详解,第1张

LIMIT关键字 mapper代码
<select id="selectByPageInfo" resultMap="BaseResult">
 select * from tb_user limit #{pageNo}, #{pageSize}
</select>
业务层直接调用
public List<User> findByPageInfo(PageInfo info) {
 return userMapper.selectByPageInfo(info);
 }

3,优点

灵活性高,可优化空间大
mysql分页语句优化

4,缺点

实现复杂。

RowBounds实现分页

Mybatis提供RowBounds类来实现逻辑分页。RowBounds中有2个字段offset和limit。这种方式获取所有的ResultSet,从ResultSet中的offset位置开始获取limit个记录。但这并不意味着JDBC驱动器会将所有的ResultSet存放在内存,实际上只加载小部分数据到内存,如果需要,再加载部分数据到内存。

mapper代码
 <select id="selectPage" resultType="com.example.demo.mapper.one.User">
        select * from user
    </select>
dao代码
    List<User> selectPage(RowBounds rowBounds);
分页查询
       List<User> users = userMapper.selectPage(new RowBounds(5, 10));
       log.info("users:{}",users);

查询结果:

users:[User(id=6, username=柳云璇, grade=小三(5)班, age=25, phone=17358053274, sex=女), User(id=7, username=酆雨寒, grade=高一(5)班, age=19, phone=15394214112, sex=女), User(id=8, username=郑春阳, grade=小三(7)班, age=24, phone=15004202411, sex=男)]
优点

使用起来比直接limit简单。

5,缺点
DB压力比较大,因为将结果暂存在db了。

Interceptor实现 自定义Interceptor
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class DefinedPageInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        //获取StatementHandler,默认的是RoutingStatementHandler
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        //获取StatementHandler的包装类
        MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
        //分隔代理对象
        while (metaObject.hasGetter("h")) {
            Object obj = metaObject.getValue("h");
            metaObject = SystemMetaObject.forObject(obj);
        }
        while (metaObject.hasGetter("target")) {
            Object obj = metaObject.getValue("target");
            metaObject = SystemMetaObject.forObject(obj);
        }
        //获取查看接口映射的相关信息
        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
        String mapId = mappedStatement.getId();
        //拦截以ByInterceptor结尾的请求,统一实现分页
        if (mapId.matches(".+ByInterceptor$")) {
            System.out.println("LOG:已触发分页拦截器");
            //获取进行数据库操作时管理参数的Handler
            ParameterHandler parameterHandler = (ParameterHandler) metaObject.getValue("delegate.parameterHandler");
            // 分页对象需要自己构建,到时候分页方法中要传入 
            //获取请求时的参数
            PageInfo info = (PageInfo) parameterHandler.getParameterObject();
            //获取原始SQL语句
            String originalSql = (String) metaObject.getValue("delegate.boundSql.sql");
            //构建分页功能的SQL语句
            String sql = originalSql.trim() + " limit " + info.getPageNum() + ", " + info.getPageSize();
            metaObject.setValue("delegate.boundSql.sql", sql);
        }
        //调用原对象方法,进入责任链下一级
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        //生成Object对象的动态代理对象
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        //如果分页每页数量是统一的,可以在这里进行统一配置,也就无需再传入PageInfo信息了
    }
}
添加到mybatis中
 @Bean("oneSqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory() {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        try {
            sqlSessionFactoryBean.setMapperLocations(
                    // 设置mybatis的xml所在位置
                    new PathMatchingResourcePatternResolver().getResources("classpath*:mapping/one/*Mapper.xml"));
                    //设置自定义的插件
            sqlSessionFactoryBean.setPlugins(new DefinedPageInterceptor());
            return sqlSessionFactoryBean.getObject();
        } catch (Exception e) {
            return null;
        }
    }
mapper方法
   /**
     * Interceptor 实现分页,必须以ByInterceptor结构,自定义的Interceptor才能
     * 识别出来,并且必须传入PageInfo
     * @param pageInfo 自定义的分页
     * @return
     */
    List<User> selectPageByInterceptor(PageInfo pageInfo);

xml

  <select id="selectPageByInterceptor" resultType="com.example.demo.mapper.one.User">
        select * from user
    </select>
运行
 /**
     * 自定义PageInterceptor分页
     */
    @Test
    public void test04() {
        PageInfo pageInfo=new PageInfo();
        pageInfo.setPageNum(5);
        pageInfo.setPageSize(5);
        List<User> users = userMapper.selectPageByInterceptor(pageInfo);
        log.info("users:{}",users);
    }

拦截更改后的sql。

运行结果
users:[User(id=6, username=柳云璇, grade=小三(5), age=25, phone=17358053274, sex=), User(id=7, username=酆雨寒, grade=高一(5), age=19, phone=15394214112, sex=), User(id=8, username=郑春阳, grade=小三(7), age=24, phone=15004202411, sex=)]
PageHelper

PageHelper是一个第三方实现的分页拦截器插件,使用起来灵活且方便。

添加pom
 <dependency>
    <groupId>com.github.pagehelpergroupId>
    <artifactId>pagehelperartifactId>
    <version>最新版本version>
dependency>
 

2,使用方式

//第一种,RowBounds方式的调用
List<User> list = sqlSession.selectList("x.y.selectIf", null, new RowBounds(0, 10));

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

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

//第四种,参数方法调用
//存在以下 Mapper 接口方法,你不需要在 xml 处理后两个参数
public interface CountryMapper {
    List<User> selectByPageNumSize(
            @Param("user") User user,
            @Param("pageNum") int pageNum, 
            @Param("pageSize") int pageSize);
}
//配置supportMethodsArguments=true
//在代码中直接调用:
List<User> list = userMapper.selectByPageNumSize(user, 1, 10);

//第五种,参数对象
//如果 pageNum 和 pageSize 存在于 User 对象中,只要参数有值,也会被分页
//有如下 User 对象
public class User {
    //其他fields
    //下面两个参数名和 params 配置的名字一致
    private Integer pageNum;
    private Integer pageSize;
}
//存在以下 Mapper 接口方法,你不需要在 xml 处理后两个参数
public interface CountryMapper {
    List<User> selectByPageNumSize(User user);
}
//当 user 中的 pageNum!= null && pageSize!= null 时,会自动分页
List<User> list = userMapper.selectByPageNumSize(user);

//第六种,ISelect 接口方式
//jdk6,7用法,创建接口
Page<User> page = PageHelper.startPage(1, 10).doSelectPage(new ISelect() {
    @Override
    public void doSelect() {
        userMapper.selectGroupBy();
    }
});
//jdk8 lambda用法
Page<User> page = PageHelper.startPage(1, 10).doSelectPage(()-> userMapper.selectGroupBy());

//也可以直接返回PageInfo,注意doSelectPageInfo方法和doSelectPage
pageInfo = PageHelper.startPage(1, 10).doSelectPageInfo(new ISelect() {
    @Override
    public void doSelect() {
        userMapper.selectGroupBy();
    }
});
//对应的lambda用法
pageInfo = PageHelper.startPage(1, 10).doSelectPageInfo(() -> userMapper.selectGroupBy());

//count查询,返回一个查询语句的count数
long total = PageHelper.count(new ISelect() {
    @Override
    public void doSelect() {
        userMapper.selectLike(user);
    }
});
//lambda
total = PageHelper.count(()->userMapper.selectLike(user));
官网

官网:https://pagehelper.github.io/

使用方式:https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md

欢迎分享,转载请注明来源:内存溢出

原文地址:http://outofmemory.cn/sjk/996424.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-21
下一篇2022-05-21

随机推荐

  • 德克萨斯农业机械国际大学很黑吗

      德克萨斯农业机械国际大学很黑吗?德克萨斯农业机械国际大学属正规院校,具体请咨询立思辰留学360美国留学顾问,热线电话:4008-941-360院校介绍美国德克萨斯农业机械国际大学隶属创建于1876

    2022-07-07
    000
  • 埃弗里特社区大学回国好就业吗

      埃弗里特社区大学回国好就业吗?埃弗里特社区大学毕业生回国就业前景不错,具体请咨询立思辰留学360美国留学顾问,热线电话:4008-941-360院校介绍美国埃弗里特社区大学始建于1941年,是一所

    2022-07-07
    300
  • 英国兰卡斯特大学的学生服务

    兰卡斯特大学成立于1964年,是英国10大科研性大学之一,其教学质量也一直名列前茅。该校的校园景色优美,乘公共汽车到兰卡斯特市中心只需要10分钟。立思辰留学360指出,兰卡斯特大学的学术成就享誉全球,

    2022-07-07
    000
  • 东英吉利大学品牌课程包括什么

    东英吉利大学(University of East Anglia,简称UEA,又译作东英吉利大学,东英格兰大学),位于英国诺里奇(Norwich)。从1963年创校至今,东英吉利大学特别在传媒、文学、

  • 泰国国王科技大学概况

    泰国国王科技大学概况立思辰留学360介绍,国王科技大学是位于泰国曼谷的一所著名高等学府,是泰国顶尖的高科技大学,共有三个校区,其学历学分全球高校认可。在2013、2012年泰晤士报世界大学排名中,泰国

    2022-07-07
    300
  • 朱拉隆功大学留学费用大概要多少

      朱拉隆功大学朱拉隆功大学(泰语:,英语:ChulalongkornUniversity)是泰国最古老的大学,被尊为“全国最有威望的大学”。大学拥有19个学院、2个研究生学校、1个分校、11个研究所

  • 曼谷大学师生怎样

    曼谷大学立思辰留学360介绍,曼谷大学是以一颗紫色和橙色的金钻为标志的,英语 BANGKOK UNIVESITY(曼谷大学)和泰文(曼谷大学)在其一旁,标志中的紫色和橙色是曼谷大学的代表色,这颗独特而

    2022-07-07
    300
  • 2017年美国乔治华盛顿大学学生服务

    立思辰留学360介绍,美国乔治华盛顿大学(The George Washington University,简称GW)成立于1821年,是一所四年制私立大学,位于美国首都华盛顿,距美国白宫只有4个街区

    2022-07-07
    000
  • 2017年美国普林斯顿大学教学质量

    普林斯顿大学(Princeton University),简称普林斯顿,是世界著名私立研究型大学,位于美国新泽西州的普林斯顿市,是八所常春藤盟校之一。学校于1746年在新泽西州伊丽莎白镇创立,是美国殖

    2022-07-07
    300

发表评论

登录后才能评论

评论列表(0条)

    保存