请说明 MyBatis 实现分页的方式有哪些,并解释常见分页插件(如 PageHelper)的工作原理。
考察说明
考查 MyBatis 分页机制及分页插件拦截器原理
回答思路
- 【回答框架 1】MyBatis 分页主要有两种方式:一是通过传入参数在 SQL 中手动拼接 LIMIT/OFFSET 或 ROWNUM 等方言语法,由开发者自己控制;二是使用分页插件,如 PageHelper,通过拦截器自动生成分页 SQL。手动方式简单直接,但不同数据库方言不同,且无法统一处理 count 查询。
- 【回答框架 2】分页插件原理基于 MyBatis 的插件机制(Interceptor)。插件实现 Interceptor 接口,拦截 Executor 的 query 方法。当执行查询时,插件拦截到参数,判断是否有分页参数(如 PageHelper 通过 ThreadLocal 存储分页信息),若存在则先执行 count 查询获得总记录数,再修改原始 SQL 为分页 SQL(根据方言生成对应 limit/offset 或 rownum),然后将分页参数注入到查询中。
- 【回答框架 3】执行过程:插件在执行器查询前拦截,调用 MetaObject 获取原 SQL,通过 Dialect 对象生成分页 SQL,并设置参数到 BoundSql,然后继续执行。同时,PageHelper 将 count 查询和分页查询合并或分开执行,最后封装成 Page 对象(继承 ArrayList)并设置 total、pageNum 等属性,便于前端使用。
- 【回答框架 4】分页插件需要注意:数据库方言支持,不同数据库分页语法不同;count 查询的性能优化;插件对嵌套查询、存储过程等特殊场景的处理;以及插件在 MyBatis 二级缓存中的行为。合理使用分页插件能简化开发,但需结合索引优化,避免深分页性能问题。
- 【关键点 1】MyBatis 分页本质是生成带分页方言的 SQL,插件通过拦截 Executor 自动完成。
- 【关键点 2】分页插件核心是自定义 Interceptor 拦截 query 方法,通过 Dialect 生成不同数据库的分页语句。
- 【关键点 3】PageHelper 使用 ThreadLocal 传递分页参数,并封装返回 Page 对象。
- 【关键点 4】count 查询与分页查询分离,插件负责生成 count SQL 并设置总记录数。
- 【关键点 5】分页插件不改变业务逻辑,但需注意深分页和 count 性能。