Mybatis利用拦截器做统一分页
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利用拦截器做统一分页的更多相关文章
- Mybatis拦截器介绍及分页插件
1.1 目录 1.1 目录 1.2 前言 1.3 Interceptor接口 1.4 注册拦截器 1.5 Mybatis可拦截的方法 1.6 利用拦截器进行分页 1.2 前言 拦截器的一 ...
- MyBatis实现拦截器分页功能
1.原理 在mybatis使用拦截器(interceptor),截获所执行方法的sql语句与参数. (1)修改sql的查询结果:将原sql改为查询count(*) 也就是条数 (2)将语句sql进行拼 ...
- MyBatis 拦截器 (实现分页功能)
由于业务关系 巴拉巴拉巴拉 好吧 简单来说就是 原来的业务是 需要再实现类里写 selectCount 和selectPage两个方法才能实现分页功能 现在想要达到效果是 只通过一个方法就可以实现 也 ...
- Mybatis Interceptor 拦截器原理 源码分析
Mybatis采用责任链模式,通过动态代理组织多个拦截器(插件),通过这些拦截器可以改变Mybatis的默认行为(诸如SQL重写之类的),由于插件会深入到Mybatis的核心,因此在编写自己的插件前最 ...
- Mybatis之拦截器原理(jdk动态代理优化版本)
在介绍Mybatis拦截器代码之前,我们先研究下jdk自带的动态代理及优化 其实动态代理也是一种设计模式...优于静态代理,同时动态代理我知道的有两种,一种是面向接口的jdk的代理,第二种是基于第三方 ...
- mybatis Interceptor拦截器代码详解
mybatis官方定义:MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis ...
- mybatis定义拦截器
applicationContext.xml <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlS ...
- springboot+springmvc拦截器做登录拦截
springboot+springmvc拦截器做登录拦截 LoginInterceptor 实现 HandlerInterceptor 接口,自定义拦截器处理方法 LoginConfiguration ...
- [Java]利用拦截器和自定义注解做登录以及权限验证
1.自定义注解 需要验证登录的注解 package com.etaofinance.wap.common; import java.lang.annotation.Documented; import ...
随机推荐
- Windows安装openssl
Windows下有两种方式安装openssl,第一种是采用安装包方式进行安装,第二种是采用编译源码方式进行安装.这里采用第一种方式,简单,直接. windows的openssl安装包的下载地址为:ht ...
- Python KafkaProducer and KafkaConsumer的开发模块
1.在python中往kakfa写数据和读取数据,使用的是python-kafka库 2.消费者需持续写入数据,因groupid存在偏移量,才能看看到数据. 3.安装库的命令为pip install ...
- printf重定向问题
1.使用printf库函数时,要加入头文件<stdio.h> 2.另外在keil里面需要把:use MicroLIB 勾选上,不然程序没办法在线调试.编译的时候不会报错. 3.当然可以不用 ...
- SQL-还原数据库,数据库提示正在还原中的处理办法
还原数据库时,提示还原成功,可是数据库列表中该数据库显示正在还原中: 执行此命令即可: RESTORE DATABASE EnterPriseBuilding WITH RECOVERY 1. 至少有 ...
- MySQL的笔记
一. SELECT tmp2.name,tmp2.browseNum FROM (SELECT tmp.`name`, COUNT(tmp.id) AS browseNum FROM(SELECT ...
- Caused by: java.lang.ClassNotFoundException: org.springframework.boot.bind.RelaxedPropertyResolver
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.bind.RelaxedPropertyResolver 这 ...
- css一边固定,另一边自适应的方法
第一种: 第二种:
- debug?用对拍!
很多人考noip之类的比赛永远会发生一些奇怪的问题 比如说下面这两位(来自我的两位学长) sliver n:spli,考得怎样啊? spli:就那样啦,day1T1没推出来规律,别的还好 silver ...
- 随机获取指定范围内N个不重复数字
/// <summary> /// 随机获取指定范围内N个不重复数字 /// </summary> /// <param name="min"> ...
- Linux相关网络命令
1.简述osi七层模型和TCP/IP四层模型 OSI七层模型 TCP/IP四层模型 2.简述iproute家族命令 ip命令: ip [OPTIONS] OBJECT {COMMAND|help} i ...