MyBatis拦截器实现分页功能实例
发布时间 - 2026-01-11 00:44:12 点击率:次由于业务关系 巴拉巴拉巴拉

好吧 简单来说就是
原来的业务是 需要再实现类里写 selectCount 和selectPage两个方法才能实现分页功能
现在想要达到效果是 只通过一个方法就可以实现 也就是功能合并 所以就有了下面的实践
既然是基于MyBatis 所以就先搭建一个Mybatis的小项目
1.01导入 mybatis和mysql的包
1.02.配置文件 Configuration.xml 中添加
<environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test" /> <property name="username" value="root"/> <property name="password" value=""/> </dataSource> </environment> </environments>
2.01.然后创建一个模块user 创建user表
DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` char(32) NOT NULL, `t1` char(32) DEFAULT NULL, `t2` char(32) DEFAULT NULL, `t3` char(32) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
3.01.写对应bean:User.java
package lqb.bean;
public class User extends Common{
private String id;
private String name;
private String t1;
private String t2;
private String t3;
//省略get set
}
3.02.对应的mapper: UserMapper.java和UserMapper.xml
简单实现下CRUD
public interface UserMapper {
public User selectByID(int id);
public List<User> select();
public int insert(User u);
public int update(User u);
public int delete(User u);
}
<mapper namespace="lqb.mapper.UserMapper">
<select id="selectByID" parameterType="int" resultType="lqb.bean.User">
select * from `user` where id = #{id}
</select>
<select id="select" resultType="lqb.bean.User" parameterType="lqb.bean.User">
select * from `user`
</select>
<insert id="insert" parameterType="lqb.bean.User">
insert into user (id,name,t1,t2,t3) values (#{id},#{name},#{t1},#{t2},#{t3})
</insert>
<update id="update" parameterType="lqb.bean.User">
update user set name=#{name},t1=#{t1},t2=#{t2},t3=#{t3} where id=#{id}
</update>
<delete id="delete" parameterType="lqb.bean.User">
delete from user where id=#{id}
</delete>
</mapper>
3.03.然后 在配置文件Configuration.xml中添加user的配置
<mappers> <mapper resource="lqb/mapper/UserMapper.xml"/> </mappers>
3.04.然后是实现:UserService.java
public class UserService {
private static SqlSessionFactory sqlSessionFactory;
private static Reader reader;
static{
try{
reader = Resources.getResourceAsReader("Configuration.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
}catch(Exception e){
e.printStackTrace();
}
}
public static SqlSessionFactory getSession(){
return sqlSessionFactory;
}
}
4.01 好 然后是重点了
思路: 截获查询的sql 然后拼成 sqlPage和sqlCount 再进行查找取值 然后赋传入对象
所以我们就需要创建一个基础类来让user.java来继承
public class Common {
private int pagesize;
private int pageid;
private int pagebegin;
private int count;
//省略 get set
}
4.02 然后 让User继承Common
public class User extends Common{
4.03 那怎么截获sql呢 我们就要写一个mybatis的拦截器 用来拦截sql请求 PageInterceptor
@Intercepts({
@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class}),
@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
})
public class PageInterceptor implements Interceptor {
//插件运行的代码,它将代替原有的方法
@Override
public Object intercept(Invocation invocation) throws Throwable {
}
// 拦截类型StatementHandler
@Override
public Object plugin(Object target) {
}
@Override
public void setProperties(Properties properties) {
}
4.04 首先 设置拦截类型 重写plugin方法
@Override
public Object plugin(Object target) {
if (target instanceof StatementHandler) {
return Plugin.wrap(target, this);
} else {
return target;
}
}
4.05 然后 就要重写最重要的intercept了
这里我们有一个设定 如果查询方法含有searchpage 就进行分页 其他方法无视
所以就要获取方法名
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
MappedStatement mappedStatement=(MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement");
String selectId=mappedStatement.getId();
4.06 然后判断下 如果含有searchpage 就获取sql
BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql");
// 分页参数作为参数对象parameterObject的一个属性
String sql = boundSql.getSql();
Common co=(Common)(boundSql.getParameterObject());
4.07 然后 根据这个sql 重新拼写countsql和pagesql
String countSql=concatCountSql(sql);
String pageSql=concatPageSql(sql,co);
...
public String concatCountSql(String sql){
StringBuffer sb=new StringBuffer("select count(*) from ");
sql=sql.toLowerCase();
if(sql.lastIndexOf("order")>sql.lastIndexOf(")")){
sb.append(sql.substring(sql.indexOf("from")+4, sql.lastIndexOf("order")));
}else{
sb.append(sql.substring(sql.indexOf("from")+4));
}
return sb.toString();
}
public String concatPageSql(String sql,Common co){
StringBuffer sb=new StringBuffer();
sb.append(sql);
sb.append(" limit ").append(co.getPagebegin()).append(" , ").append(co.getPagesize());
return sb.toString();
}
4.08 然后 通过jdbc查询count 然后把值绑定给common
Connection connection = (Connection) invocation.getArgs()[0];
PreparedStatement countStmt = null;
ResultSet rs = null;
int totalCount = 0;
try {
countStmt = connection.prepareStatement(countSql);
rs = countStmt.executeQuery();
if (rs.next()) {
totalCount = rs.getInt(1);
}
} catch (SQLException e) {
System.out.println("Ignore this exception"+e);
} finally {
try {
rs.close();
countStmt.close();
} catch (SQLException e) {
System.out.println("Ignore this exception"+ e);
}
}
//绑定count
co.setCount(totalCount);
4.09 再把pagesql赋给元BoundSql
metaStatementHandler.setValue("delegate.boundSql.sql", pageSql);
4.10 最后在配置文件中添加拦截器配置
<plugins> <plugin interceptor="lqb.interceptor.PageInterceptor"/> </plugins>
4.11 好然后 在UserMapper.java和UserMapper.xml中添加分页代码
<select id="selectPage" parameterType="lqb.bean.User" resultType="lqb.bean.User"> select * from `user` where id in(3,4,6,8) order by id </select>
public List<User> selectPage(User u);
5.01 最后是测试了
main...请允许本人的懒 就姑且在main方法测下吧
User u=new User();
u.setPagebegin(2);
u.setPagesize(3);
System.out.println("-u.getCount()------"+u.getCount());
List<User> l=userService.selectPage(u);
System.out.println(l.size());
System.out.println("-u.getCount()------"+u.getCount());
5.02 结果 略 然后就成功了
下面附上拦截器的代码
package lqb.interceptor;
import java.util.Properties;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import java.sql.*;
import lqb.bean.Common;
@Intercepts({
@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class}),
@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
})
public class PageInterceptor implements Interceptor {
private static final String SELECT_ID="selectpage";
//插件运行的代码,它将代替原有的方法
@Override
public Object intercept(Invocation invocation) throws Throwable {
System.out.println("PageInterceptor -- intercept");
if (invocation.getTarget() instanceof StatementHandler) {
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
MappedStatement mappedStatement=(MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement");
String selectId=mappedStatement.getId();
if(SELECT_ID.equals(selectId.substring(selectId.lastIndexOf(".")+1).toLowerCase())){
BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql");
// 分页参数作为参数对象parameterObject的一个属性
String sql = boundSql.getSql();
Common co=(Common)(boundSql.getParameterObject());
// 重写sql
String countSql=concatCountSql(sql);
String pageSql=concatPageSql(sql,co);
System.out.println("重写的 count sql :"+countSql);
System.out.println("重写的 select sql :"+pageSql);
Connection connection = (Connection) invocation.getArgs()[0];
PreparedStatement countStmt = null;
ResultSet rs = null;
int totalCount = 0;
try {
countStmt = connection.prepareStatement(countSql);
rs = countStmt.executeQuery();
if (rs.next()) {
totalCount = rs.getInt(1);
}
} catch (SQLException e) {
System.out.println("Ignore this exception"+e);
} finally {
try {
rs.close();
countStmt.close();
} catch (SQLException e) {
System.out.println("Ignore this exception"+ e);
}
}
metaStatementHandler.setValue("delegate.boundSql.sql", pageSql);
//绑定count
co.setCount(totalCount);
}
}
return invocation.proceed();
}
/**
* 拦截类型StatementHandler
*/
@Override
public Object plugin(Object target) {
if (target instanceof StatementHandler) {
return Plugin.wrap(target, this);
} else {
return target;
}
}
@Override
public void setProperties(Properties properties) {
}
public String concatCountSql(String sql){
StringBuffer sb=new StringBuffer("select count(*) from ");
sql=sql.toLowerCase();
if(sql.lastIndexOf("order")>sql.lastIndexOf(")")){
sb.append(sql.substring(sql.indexOf("from")+4, sql.lastIndexOf("order")));
}else{
sb.append(sql.substring(sql.indexOf("from")+4));
}
return sb.toString();
}
public String concatPageSql(String sql,Common co){
StringBuffer sb=new StringBuffer();
sb.append(sql);
sb.append(" limit ").append(co.getPagebegin()).append(" , ").append(co.getPagesize());
return sb.toString();
}
public void setPageCount(){
}
}
最后是下载地址:mybatisResolve_jb51.rar
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# mybatis
# 拦截器
# 分页
# mybatis分页拦截
# mybatis的分页拦截器
# Mybatis Limit实现分页功能
# Mybatis实现联表查询并且分页功能
# Mybatis Plus 自定义方法实现分页功能的示例代码
# MyBatis拦截器实现分页功能的实现方法
# Spring MVC+MyBatis+MySQL实现分页功能实例
# MyBatis超详细讲解如何实现分页功能
# 重写
# 绑定
# 配置文件
# 巴拉
# 它将
# 创建一个
# 下载地址
# 最重要
# 点了
# 好吧
# 就先
# 再把
# 大家多多
# 要写
# 就可以
# 下吧
# 有一个
# 拼成
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
网站视频制作书签怎么做,ie浏览器怎么将网站固定在书签工具栏?
太平洋网站制作公司,网络用语太平洋是什么意思?
logo在线制作免费网站在线制作好吗,DW网页制作时,如何在网页标题前加上logo?
Laravel项目结构怎么组织_大型Laravel应用的最佳目录结构实践
Laravel Octane如何提升性能_使用Laravel Octane加速你的应用
如何在IIS中新建站点并配置端口与IP地址?
JavaScript 输出显示内容(document.write、alert、innerHTML、console.log)
如何使用 jQuery 正确渲染 Instagram 风格的标签列表
西安市网站制作公司,哪个相亲网站比较好?西安比较好的相亲网站?
如何使用 Go 正则表达式精准提取括号内首个纯字母标识符(忽略数字与嵌套)
Laravel如何为API生成Swagger或OpenAPI文档
Laravel怎么进行数据库事务处理_Laravel DB Facade事务操作确保数据一致性
米侠浏览器网页背景异常怎么办 米侠显示修复
php后缀怎么变mp4格式错误_修改扩展名提示格式不对怎么办【技巧】
如何在IIS7中新建站点?详细步骤解析
用v-html解决Vue.js渲染中html标签不被解析的问题
JS经典正则表达式笔试题汇总
如何彻底删除建站之星生成的Banner?
如何彻底卸载建站之星软件?
Laravel如何实现API版本控制_Laravel版本化API设计方案
如何用PHP快速搭建高效网站?分步指南
免费网站制作appp,免费制作app哪个平台好?
如何快速查询网址的建站时间与历史轨迹?
CSS3怎么给轮播图加过渡动画_transition加transform实现【技巧】
Laravel怎么实现观察者模式Observer_Laravel模型事件监听与解耦开发【指南】
软银砸40亿美元收购DigitalBridge 强化AI资料中心布局
Laravel如何实现本地化和多语言支持_Laravel多语言配置与翻译文件管理
Laravel如何获取当前用户信息_Laravel Auth门面获取用户ID
如何实现javascript表单验证_正则表达式有哪些实用技巧
微信小程序 canvas开发实例及注意事项
Laravel如何升级到最新版本?(升级指南和步骤)
Win11怎样安装网易有道词典_Win11安装词典教程【步骤】
Android使用GridView实现日历的简单功能
Laravel如何使用Blade模板引擎?(完整语法和示例)
如何快速辨别茅台真假?关键步骤解析
iOS正则表达式验证手机号、邮箱、身份证号等
网站制作报价单模板图片,小松挖机官方网站报价?
php8.4header发送头信息失败怎么办_php8.4header函数问题解决【解答】
米侠浏览器网页图片不显示怎么办 米侠图片加载修复
Laravel如何发送系统通知?(Notification渠道示例)
微信小程序 require机制详解及实例代码
企业在线网站设计制作流程,想建设一个属于自己的企业网站,该如何去做?
进行网站优化必须要坚持的四大原则
个人摄影网站制作流程,摄影爱好者都去什么网站?
制作公司内部网站有哪些,内网如何建网站?
javascript中对象的定义、使用以及对象和原型链操作小结
宙斯浏览器怎么屏蔽图片浏览 节省手机流量使用设置方法
移动端手机网站制作软件,掌上时代,移动端网站的谷歌SEO该如何做?
Linux安全能力提升路径_长期防护思维说明【指导】
为什么要用作用域操作符_php中访问类常量与静态属性的优势【解答】

