mybatis利用拦截器做统一分页

查询传递Page参数,或者传递继承Page的对象参数。拦截器查询记录之后,通过改造查询sql获取总记录数。赋值Page对象,返回。

示例项目:https://github.com/windwant/spring-boot-service

https://github.com/windwant/spring-dubbo-service/tree/master/spring-boot-server

拦截器:

package com.xxx;

import com.xxx.Page;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties; /**
*/
@Intercepts({//拦截query查询
@Signature(type=Executor.class,method="query",args={MappedStatement.class,Object.class,RowBounds.class,ResultHandler.class})
})
public class PageIntercept implements Interceptor { public static final Logger logger = LoggerFactory.getLogger(PageIntercept.class); @Override
public Object intercept(Invocation invocation) throws Throwable {
Object parameter = invocation.getArgs()[1];
Object args = invocation.getArgs()[1];
Object returnValue = invocation.proceed();
if(args instanceof Page && ((Page) args).isCount()){
MappedStatement mappedStatement=(MappedStatement)invocation.getArgs()[0];
BoundSql boundSql = mappedStatement.getBoundSql(parameter);
String originalSql = boundSql.getSql().trim();
Object parameterObject = boundSql.getParameterObject();
if(parameterObject instanceof Page){
((Page) parameterObject).setOffset(0);
((Page) parameterObject).setLimit(Integer.MAX_VALUE/((Page) parameterObject).getPage());
} String countSql = "SELECT COUNT(*) FROM (" + originalSql + ") aliasForPage";
Connection connection=mappedStatement.getConfiguration().getEnvironment().getDataSource().getConnection(); BoundSql countBS = copyFromBoundSql(mappedStatement, boundSql, countSql);
DefaultParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, parameterObject, countBS);
PreparedStatement countStmt = connection.prepareStatement(countSql);
parameterHandler.setParameters(countStmt);
ResultSet rs = countStmt.executeQuery();
int total =0;
if (rs.next()) {
total = rs.getInt(1);
}
rs.close();
countStmt.close();
connection.close();
//分页计算
((Page) args).setTotal(total);
} return returnValue;
} private BoundSql copyFromBoundSql(MappedStatement ms, BoundSql boundSql, String sql) {
BoundSql newBoundSql = new BoundSql(ms.getConfiguration(),sql, boundSql.getParameterMappings(), boundSql.getParameterObject());
for (ParameterMapping mapping : boundSql.getParameterMappings()) {
String prop = mapping.getProperty();
if (boundSql.hasAdditionalParameter(prop)) {
newBoundSql.setAdditionalParameter(prop, boundSql.getAdditionalParameter(prop));
}
}
return newBoundSql;
} @Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
} @Override
public void setProperties(Properties properties) { } }

数据库配置:

package com.xxx.config;

import javax.sql.DataSource;

import com.xxx.PageIntercept;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager; /**
* @description
*/ @Configuration
@MapperScan(basePackages = "com.xxx.dao", sqlSessionFactoryRef = "sqlSessionFactory")
public class DBConfig { private final static Logger logger = LoggerFactory.getLogger(DBConfig.class); @Bean(name = "dataSource")
@ConfigurationProperties(prefix = "datasource.planes")
@Primary
public DataSource dataSource() {
return DataSourceBuilder.create().build();
} @Bean(name = "sqlSessionFactory")
@Primary
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource());
bean.setPlugins(new Interceptor[]{new PageIntercept()});
return bean.getObject();
} @Bean(name = "transactionManager")
@Primary
public DataSourceTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
} }  

Page对象:

package com.xxx;

import com.xxx.Constants;

/**
* Created by Administrator on 2018/1/5.
*/
public class Page { private int offset = 0; private int limit = Constants.DEAFULT_PAGE_LIMIT; private int total = 0; private int page = 1; private boolean count = true; public boolean isCount() {
return count;
} public void setCount(boolean count) {
this.count = count;
} public Page(){} public Page(int offset, int limit){
this. offset = offset;
this.limit = limit;
}
public int getPage() {
return page;
} public void setPage(int page) {
this.page = page < 1?1:page;
} public int getOffset() {
return (page - 1) * limit;
} public void setOffset(int offset) {
this.offset = offset;
} public int getLimit() {
return limit;
} public void setLimit(int limit) {
this.limit = limit;
} public int getTotal() {
return total;
} public void setTotal(int total) {
this.total = total;
}
}

  

Mybatis利用拦截器做统一分页的更多相关文章

  1. Mybatis拦截器介绍及分页插件

    1.1    目录 1.1 目录 1.2 前言 1.3 Interceptor接口 1.4 注册拦截器 1.5 Mybatis可拦截的方法 1.6 利用拦截器进行分页 1.2     前言 拦截器的一 ...

  2. MyBatis实现拦截器分页功能

    1.原理 在mybatis使用拦截器(interceptor),截获所执行方法的sql语句与参数. (1)修改sql的查询结果:将原sql改为查询count(*) 也就是条数 (2)将语句sql进行拼 ...

  3. MyBatis 拦截器 (实现分页功能)

    由于业务关系 巴拉巴拉巴拉 好吧 简单来说就是 原来的业务是 需要再实现类里写 selectCount 和selectPage两个方法才能实现分页功能 现在想要达到效果是 只通过一个方法就可以实现 也 ...

  4. Mybatis Interceptor 拦截器原理 源码分析

    Mybatis采用责任链模式,通过动态代理组织多个拦截器(插件),通过这些拦截器可以改变Mybatis的默认行为(诸如SQL重写之类的),由于插件会深入到Mybatis的核心,因此在编写自己的插件前最 ...

  5. Mybatis之拦截器原理(jdk动态代理优化版本)

    在介绍Mybatis拦截器代码之前,我们先研究下jdk自带的动态代理及优化 其实动态代理也是一种设计模式...优于静态代理,同时动态代理我知道的有两种,一种是面向接口的jdk的代理,第二种是基于第三方 ...

  6. mybatis Interceptor拦截器代码详解

    mybatis官方定义:MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis ...

  7. mybatis定义拦截器

    applicationContext.xml <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlS ...

  8. springboot+springmvc拦截器做登录拦截

    springboot+springmvc拦截器做登录拦截 LoginInterceptor 实现 HandlerInterceptor 接口,自定义拦截器处理方法 LoginConfiguration ...

  9. [Java]利用拦截器和自定义注解做登录以及权限验证

    1.自定义注解 需要验证登录的注解 package com.etaofinance.wap.common; import java.lang.annotation.Documented; import ...

随机推荐

  1. 将form表单元素的值序列化成对象

    /**jQuery * 将form表单元素的值序列化成对象 * @returns object */ var serializeObject = function(form) { var o = {} ...

  2. Ajax+PHP实现异步图片上传

    1.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <ti ...

  3. C编程规范, 演示样例代码。

    /*************************************************************** *Copyright (c) 2014,TianYuan *All r ...

  4. springmvc整合mybatis框架源码 bootstrap html5 mysql oracle maven SSM

    A 调用摄像头拍照,自定义裁剪编辑头像 [新录针对本系统的视频教程,手把手教开发一个模块,快速掌握本系统]B 集成代码生成器 [正反双向](单表.主表.明细表.树形表,开发利器)+快速构建表单;  技 ...

  5. 使用XWAF框架(3)——下载文件

    XWAF提供了HttpFileDownloader类用于简化用户下载文件的编码.该类提供了重载方法“downloadFile(String filePath, String fName)”实现下载.程 ...

  6. Oracle AWR与警报系统一

    管理自动工作负荷知识库 Oracle收集大量有关性能和活动的统计信息.这些信息在内存中积累,并定期写入数据库:写入到构成自动工作负荷知识库(Automatic Workload Repository, ...

  7. 谈谈对html5的了解

    1.良好的移动性,以移动端设备为主. 2.响应式设计,以适应自动变化的屏幕尺寸. 3.支持离线缓存技术,webStorage本地缓存. 4.新增canvas,video,audio等新.标签元素.新增 ...

  8. encodeURIComponent编码反斜杠 \ (正则匹配)

    记录一个小bug... 前言废话: 1. 功能需求:修改输入框的内容,获取字符串传给后端保存. 2. bug历程:刚开始直接获取value值传过去.后来测试发现%&这些特殊字符无法传递后,在前 ...

  9. LEFT JOIN个别问题

    SELECT a.loginuser, a.schoolid, count(b.id)FROM vhs_school AS aLEFT JOIN vhs_attence AS b ON a.schoo ...

  10. Delphi XE7的Splash 功能

    Delphi XE5,XE6,XE7编译的程序在Android下启动会有一段时间黑屏,以前需要用Java扩展Activity增加Splash显示, 现在Delphi XE7增加了Splash Imag ...