MyBatis分页的四种方式

 更新时间:2024年08月04日 09:55:43   作者:Itmastergo  
分页查询是非常常见的需求,本文主要介绍了MyBatis分页的四种方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

MyBatis 是一个优秀的持久层框架,它为开发人员提供了一种通过简单的 XML 或注解方式来操作数据库的工具。在日常开发中,分页查询是非常常见的需求。MyBatis 提供了多种实现分页的方法,主要包括以下三种:

  • 物理分页(Physical Pagination)
  • 逻辑分页(Logical Pagination)
  • 使用插件分页(Pagination with Plugins)

下面将详细讲解这三种分页方式的原理、实现步骤和各自的优缺点。

1、物理分页(Physical Pagination)

物理分页是指在 SQL 查询中直接使用数据库的分页语法,例如 LIMIT 和 OFFSET,通过 SQL 语句控制返回的数据范围。物理分页直接由数据库执行分页操作,性能相对较好。

1.1、原理

物理分页通过在 SQL 查询中加入分页条件,利用数据库的分页功能进行数据截取,返回所需的数据集。例如在 MySQL 中使用 LIMIT 和 OFFSET 实现分页。

1.2、实现步骤

1.2.1、在 XML 映射文件中配置分页 SQL

<select id="selectUsers" parameterType="map" resultType="User">
    SELECT * FROM users
    ORDER BY id
    LIMIT #{offset}, #{limit}
</select>

1.2.2、在 Java 代码中调用分页查询

Map<String, Object> params = new HashMap<>();
int page = 1;  // 页码
int pageSize = 10;  // 每页显示条数
int offset = (page - 1) * pageSize;

params.put("offset", offset);
params.put("limit", pageSize);

List<User> users = session.selectList("selectUsers", params);

1.3、优点

  • 性能高:分页操作在数据库端完成,减少了网络传输的数据量。
  • 简单直接:实现方式简单,直接在 SQL 中添加分页参数。

1.4、缺点

  • 数据库依赖:分页语法依赖于具体的数据库实现,不同数据库的分页语法不同。
  • 代码重复:每个分页查询都需要重复编写分页 SQL。

2、逻辑分页(Logical Pagination)

逻辑分页是指在内存中进行分页操作,先查询出所有数据,然后在应用层进行分页。逻辑分页适用于数据量较小的情况,数据量较大时不推荐使用。

2.1、原理

逻辑分页通过在应用层对查询结果进行截取,返回所需的分页数据。先执行不带分页条件的查询,获取所有数据后,再根据分页参数截取子集。

2.2、实现步骤

2.2.1、在 XML 映射文件中配置查询 SQL

<select id="selectAllUsers" resultType="User">
    SELECT * FROM users
</select>

2.2.2、在 Java 代码中进行逻辑分页

List<User> allUsers = session.selectList("selectAllUsers");

int page = 1;  // 页码
int pageSize = 10;  // 每页显示条数
int start = (page - 1) * pageSize;
int end = Math.min(start + pageSize, allUsers.size());

List<User> usersPage = allUsers.subList(start, end);

2.3、优点

  • 数据库无关:不依赖于具体的数据库分页语法,具有良好的兼容性。
  • 简单实现:无需修改 SQL 语句,分页逻辑在应用层实现。

2.4、缺点

  • 性能低:需要一次性查询出所有数据,当数据量大时会占用大量内存,查询性能较差。
  • 适用范围有限:仅适用于数据量较小的场景。

3、使用插件分页(Pagination with Plugins)

MyBatis 支持通过插件机制实现分页,这种方式在性能和使用方便性上具有很大优势。常用的分页插件有 PageHelper 和 MyBatis-Plus 提供的分页插件。

3.1、原理

分页插件通过拦截 MyBatis 执行的 SQL 语句,在执行查询前自动添加分页参数,从而实现透明的分页功能。开发者只需配置插件并调用分页方法,无需手动编写分页 SQL。

3.2、实现步骤(以 PageHelper 为例)

3.2.1、引入 PageHelper 依赖

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.2.0</version>
</dependency>

3.2.2、配置 PageHelper 插件

@Configuration
public class MyBatisConfig {
    @Bean
    public PageInterceptor pageInterceptor() {
        PageInterceptor pageInterceptor = new PageInterceptor();
        Properties properties = new Properties();
        properties.setProperty("helperDialect", "mysql");
        properties.setProperty("reasonable", "true");
        pageInterceptor.setProperties(properties);
        return pageInterceptor;
    }
}

3.2.3、在 Java 代码中使用分页插件

PageHelper.startPage(1, 10);
List<User> users = session.selectList("selectUsers");
PageInfo<User> pageInfo = new PageInfo<>(users);

3.3、优点

  • 高性能:分页操作在数据库端完成,减少网络传输的数据量,性能优于逻辑分页。
  • 使用方便:开发者无需编写分页 SQL,只需调用插件提供的方法即可实现分页功能。
  • 功能丰富:插件通常提供了丰富的分页功能,如自动计算总记录数、分页导航等。

3.4、缺点

  • 依赖第三方库:需要引入额外的依赖,并进行相应的配置。
  • 学习成本:需要学习和理解插件的使用方法和配置方式。

MyBatis 提供的三种分页方式各有优缺点,开发者应根据具体的业务需求和场景选择合适的分页方式:

  • 物理分页:适用于数据量较大、对性能要求较高的场景,分页操作在数据库端完成。
  • 逻辑分页:适用于数据量较小、不依赖数据库分页语法的场景,分页操作在应用层完成。
  • 使用插件分页:通过插件实现透明分页,适用于大多数场景,兼具高性能和易用性。

在实际开发中,建议优先考虑使用分页插件,因为这种方式既保证了高性能,又简化了开发过程。同时,分页插件通常提供了更多的功能和更好的扩展性,能够满足复杂的分页需求。无论选择哪种分页方式,都需要综合考虑系统的性能、易用性和维护成本,做出最适合业务需求的决策。

4、RowBounds实现分页

RowBounds原理

  • Mybatis可以通过传递RowBounds对象,来进行数据库数据的分页操作,然而遗憾的是,该分页操作是对ResultSet结果集进行分页,也就是人们常说的逻辑分页,而非物理分页(物理分页当然就是我们在sql语句中指定limit和offset值)。
  • 不再使用SQL实现分页

RowBounds使用

1、接口

List<Map> getUserByRowBounds(Map<String,Integer> map);

2、mapper.xml

 <!--分页-->
    <select id="getUserByRowBounds" parameterType="map"  resultType="map" >
        select *
        from mybatis01.user ;
    </select>

3、测试

 @Test
    public void getUserByRowBounds(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        //RowBounds实现
        RowBounds rowBounds = new RowBounds(1,2);

        //通过java代码层面实现分页
        List<Map> userList = sqlSession.selectList("com.jin.mapper.UserMapper.getUserByRowBounds", null, rowBounds);
        for (Map map1 : userList) {
            System.out.println(map1);
        }


        sqlSession.close();
    }

RowBounds大坑

RowBounds是将所有符合条件的数据全都查询到内存中,然后在内存中对数据进行分页如我们查询user表中id>0的数据,然后分页查询sql如下:

select * from user where id >0 limit 3,10

但使用RowBounds后,会将id>0的所有数据都加载到内存中,然后跳过offset=3条数据,截取10条数据出来,若id>0的数据有100万,则100w数据都会被加载到内存中,从而造成内存OOM

所以当数据量非常大时,一定要慎用RowBounds类。切记!切记

到此这篇关于MyBatis分页的四种方式的文章就介绍到这了,更多相关MyBatis分页内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • springboot配置文件绑定实现解析

    springboot配置文件绑定实现解析

    这篇文章主要介绍了springboot配置文件绑定实现解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • 利用keytools为tomcat 7配置ssl双向认证的方法

    利用keytools为tomcat 7配置ssl双向认证的方法

    双向认证和单向认证原理基本差不多,只是除了客户端需要认证服务端以外,增加了服务端对客户端的认证,下面这篇文章主要介绍了利用keytools为tomcat 7配置ssl双向认证的方法,需要的朋友可以借鉴,下面来一起看看吧。
    2017-02-02
  • 详解SpringBoot AOP 拦截器(Aspect注解方式)

    详解SpringBoot AOP 拦截器(Aspect注解方式)

    这篇文章主要介绍了详解SpringBoot AOP 拦截器 Aspect,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • Java定义画板类的方法

    Java定义画板类的方法

    这篇文章主要为大家详细介绍了Java定义画板类的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • JAVA下单接口优化实战TPS性能提高10倍

    JAVA下单接口优化实战TPS性能提高10倍

    今天小编就为大家分享一篇关于JAVA下单接口优化实战TPS性能提高10倍,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • Mybatis实现动态SQL编写详细代码示例

    Mybatis实现动态SQL编写详细代码示例

    这篇文章主要为大家详细介绍了Mybatis中动态SQL的编写使用,动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,它存在的意义是为了解决拼接SQL语句字符串时的痛点问题,感兴趣想要详细了解可以参考下文
    2023-05-05
  • SpringBoot详解如果通过@Value注解给静态变量注入值

    SpringBoot详解如果通过@Value注解给静态变量注入值

    这篇文章主要介绍了springboot如何通过@Value给静态变量注入值,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • Java 类与对象重难点详解

    Java 类与对象重难点详解

    类(class)和对象(object)是两种以计算机为载体的计算机语言的合称。对象是对客观事物的抽象,类是对对象的抽象。类是一种抽象的数据类型
    2021-11-11
  • 详解spring mvc对异步请求的处理

    详解spring mvc对异步请求的处理

    spring mvc3.2及以上版本增加了对请求的异步处理,是在servlet3的基础上进行封装的,有兴趣的可以了解一下。
    2017-01-01
  • java括号匹配算法求解(用栈实现)

    java括号匹配算法求解(用栈实现)

    这篇文章主要介绍了java括号匹配算法求解(用栈实现),需要的朋友可以参考下
    2020-12-12

最新评论