最近做的项目前端是外包出去的,所以在做查询分页的时候比较麻烦

我们需要先吧结果集的条数返回给前端,然后由前端根据页面情况(当前页码,每页显示条数)将所需参数传到后端。

由于在项目搭建的时候,是没有考虑数据量比较大(结果集数量大于1W条,甚至达到30W条)的情况

(使用的VPN网络比较慢,使用单元测试,1w条数据,需要30s左右才能返回到系统上,sql本身执行在秒内可以出结果,

所以不能先把结果集拿到系统中,再返回结果集的条数,然后分页。所以需要另一个查询,返回结果集的条数

现在项目已经存在很多查询语句,项目使用的是mybatis,所有mybatis中就配了很多select(几百个),每个都去加一个对应的查询结果集条数的SQL,

不知道得吐多少老血(而且会让项目的mapper配置,膨胀很多,这是不必要的损耗)

这种场景下,使用拦截器,在查询中动态获取SQL,添加查询结果集的语句(select count(*) from (原来的sql)),就是合适的解决方法

这样,只需要在请求参数中添加一个参数(根据项目情况,我是这样设计的,慕课网上的案例是在select的id中添加指定字符串,如:“bypage”)

在拦截器中取出满足条件的SQL,动态的添加上(select count(*) from (原来的sql)) 就可以返回结果集的条数。

同时引用了开源的mybatis插件Mybatis_PageHelper ,所有在使用拦截器的时候,加了一个判断,是不是需要分页的查询

mybatis_config.xml 

<plugins>
<plugin interceptor="com.utstar.bi.interceptors.SqlInterceptorCount"> <!-- 自己写的那个拦截器 -->
<property name="dialect" value="mysql"/> <!-- mysql的方言 -->
</plugin>
</plugins>

java

package com.utstar.bi.interceptors;

import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject; import java.sql.Connection;
import java.util.HashMap;
import java.util.Properties; /**
* Created by Lenovo on 2017/6/17.
*/
@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }) })
public class SqlInterceptorCount implements Interceptor { @Override
public Object intercept(Invocation invocation) throws Throwable { StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
MetaObject metaStatementHandler = MetaObject.forObject(statementHandler);
HashMap mapParam = (HashMap) metaStatementHandler.getValue("delegate.boundSql.parameterObject");
/*
* add by venn
* if the request parameter with key count && value is sum
* then this sql just return the sql count from result
* 如果请求参数中有个值是count并且value是sum,就是我们需要拦截的查询
* mapParam.get("startItem") ==null :这句是因为同时引用了Mybatis_PageHelper
* 插件,防止SQL交叉,做的安全过滤
* */
if (mapParam.get("startItem") ==null && mapParam.get("count") != null && mapParam.get("count").toString().equalsIgnoreCase("sum")) {
// 从StatementHandler中取出查询的SQL
String sql = (String) metaStatementHandler.getValue("delegate.boundSql.sql");
//System.out.println("before sql = " +sql);
// 获取第一个from的坐标
int index = sql.indexOf("from");
// 将sql from坐标前的字符截断,加上 select count(1) coun 查询结果集条数的SQL
sql = "select count(1) coun " + sql.substring(index);
//System.out.println("after sql = " +sql);
// 将修改的SQL放回StatementHandler中
metaStatementHandler.setValue("delegate.boundSql.sql", sql);
}
// 继续执行拦截之前的操作
return invocation.proceed();
} @Override
public Object plugin(Object target) {
/*
根据Intercepts注解,拦截 StatementHandler 的prepare 方法
*/
return Plugin.wrap(target, this);
} @Override
public void setProperties(Properties properties) { }
}

mybatis拦截器案例之获取结果集总条数的更多相关文章

  1. Mybatis拦截器(六)

    拦截器的作用就是我们可以拦截某些方法的调用,在目标方法前后加上我们自己逻辑. Mybatis拦截器设计的一个初衷是为了供用户在某些时候可以实现自己的逻辑而不必去动Mybatis固有的逻辑. Mybat ...

  2. Mybatis拦截器介绍

    拦截器的一个作用就是我们可以拦截某些方法的调用,我们可以选择在这些被拦截的方法执行前后加上某些逻辑,也可以在执行这些被拦截的方法时执行自己的逻辑而不再执行被拦截的方法.Mybatis拦截器设计的一个初 ...

  3. Mybatis拦截器实现分页

    本文介绍使用Mybatis拦截器,实现分页:并且在dao层,直接返回自定义的分页对象. 最终dao层结果: public interface ModelMapper { Page<Model&g ...

  4. 数据权限管理中心 - 基于mybatis拦截器实现

    数据权限管理中心 由于公司大部分项目都是使用mybatis,也是使用mybatis的拦截器进行分页处理,所以技术上也直接选择从拦截器入手 需求场景 第一种场景:行级数据处理 原sql: select ...

  5. 基于Spring和Mybatis拦截器实现数据库操作读写分离

    首先需要配置好数据库的主从同步: 上一篇文章中有写到:https://www.cnblogs.com/xuyiqing/p/10647133.html 为什么要进行读写分离呢? 通常的Web应用大多数 ...

  6. 通过spring抽象路由数据源+MyBatis拦截器实现数据库自动读写分离

    前言 之前使用的读写分离的方案是在mybatis中配置两个数据源,然后生成两个不同的SqlSessionTemplate然后手动去识别执行sql语句是操作主库还是从库.如下图所示: 好处是,你可以人为 ...

  7. spring boot 实现mybatis拦截器

    spring boot 实现mybatis拦截器 项目是个报表系统,服务端是简单的Java web架构,直接在请求参数里面加了个query id参数,就是mybatis mapper的query id ...

  8. mybatis拦截器使用

    目录 mybatis 拦截器接口Interceptor spring boot + mybatis整合 创建自己的拦截器MyInterceptor @Intercepts注解 mybatis拦截器入门 ...

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

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

随机推荐

  1. H5入门

    1.基本骨架 <!DOCTYPE html> <html> <head><title>标题</title><meta charset= ...

  2. Struts2把数据封装到集合中之封装到Collection中

    数据封装到集合中,可以封装到集合中,也可以封装到Map中.该篇博客主要讲解数据封装到集合中的封装到Collection中. 1. 封装复杂类型的参数(集合类型 Collection .Map接口等) ...

  3. Struts2框架的数据封装一之属性封装(属性封装的第二种方式:封装成javaBean)

    Struts2中提供了两类数据封装的方式? 第一种方式:属性驱动(有两种方式:一个对属性,另外一个是将参数封装到javaBean中) B. 在页面上,使用OGNL表达式进行数据封装.(将参数封装到ja ...

  4. MVC之CodeFirst

    1.建立MVC项目>NuGet安装EF 2.建立模型: public class Blog { [Key] [DatabaseGenerated(DatabaseGeneratedOption. ...

  5. 9.12 h5日记

    9.12 知识点补充: 属性继承例子,color.font(font-size/style/family/weight) 1.浏览器的默认字体大小是16px,谷歌浏览器的最小字体是10px,其他浏览器 ...

  6. (轉)EasyUI - DataGrid 去右边空白滚动条列

    熟悉 EasyUI - DataGrid 的童鞋应该会注意到这样一个情景: 想去掉这块,找了下资料,发现也有人同样纠结:http://www.cnblogs.com/hantianwei/p/3440 ...

  7. 十年百度工作心得(月薪75k)

    百度,是多少从事IT事业的程序员梦寐以求的地方,能进入这样大厂的程序员可以说都是数一数二的人才. 最近有不少朋友问,成为百度,腾讯,阿里Java架构师需要系统学习哪些Java技术. 下面分享互联网Ja ...

  8. iOS最全的常用正则表达式大全

    很多不太懂正则的朋友,在遇到需要用正则校验数据时,往往是在网上去找很久,结果找来的还是不很符合要求.所以我最近把开发中常用的一些正则表达式整理了一下,包括校验数字.字符.一些特殊的需求等等.给自己留个 ...

  9. Delphi中静态方法重载还是覆盖的讨论

    Delphi中静态方法重载还是覆盖的讨论 新人学习Delphi的时候,容易搞不懂的一个问题,当子类方法和基类方法同名,并且参数也一样的时候,叫做什么呢?是覆盖,还是重载呢? 答案是隐藏父类方法. 一般 ...

  10. JSP自定义标签(标签处理器 tld文件)

    标签的形式如下,标签处理器就是处理JSP页面中的标签的属性和内容,定义好之后就跟使用JSTL一样 <标签名 属性名="属性值" 属性名="属性值"> ...