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

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

由于在项目搭建的时候,是没有考虑数据量比较大(结果集数量大于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. codeforces 722D Generating Sets 【优先队列】

    You are given a set Y of n distinct positive integers y1, y2, ..., yn. Set X of n distinct positive ...

  2. Java字符串String详解

    1.String字符串 实例化String对象: (1)直接赋值,如:String str="hello"; (2)使用关键字 new,如:String str=new Strin ...

  3. MySQL之开启远程连接

    MySQL安装时,默认只能本地连接. mysql -u root -p mysql>use mysql; mysql>select 'host' from user where user= ...

  4. js阻止时间冒泡事件——event.stopPropagation()

    1. 作用:不再派发事件. 2. 语法: html代码: <div class="oreder-cont" ng-click="Orderdetails()&quo ...

  5. [剑指offer]51-数组中的逆序对(归并排序)

    题目链接 https://www.nowcoder.com/questionTerminal/96bd6684e04a44eb80e6a68efc0ec6c5 题意 在数组中的两个数字,如果前面一个数 ...

  6. 1.尽量以const ,enum,inline替换define

    1.#define为预处理阶段命令 原因:有可能记号名称没有进入记号表,而出现编译错误,即编译器并没看到过该定义. class专属常量const 一般定义为static,保证该常量至多有一份实体. 枚 ...

  7. 使用python读写CSV文件

    # -*- coding:UTF-8 -*- __autor__ = 'zhouli' __date__ = '2018/10/25 21:14' import csv with open('resu ...

  8. 联想G510安装win7系统

    1.插入系统盘重启(要按Fn+f12) 2默认下一步 3.选择自定义 4.选择需要将系统安装到的分区,格式化,然后下一步 5.默认下一步 安装到这里就成功了 6.问题处理: 第4步时出现 Window ...

  9. centos更换yum源为aliyun源

    国外的yum源由于众所周知的GFW原因,有的被墙,有的很慢,阿里云依靠强大的技术优势建立了国内的开源镜像.阿里云Linux安装镜像源地址:http://mirrors.aliyun.com/ 第一步: ...

  10. python re正则

    一:什么是正则? 正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法.或者说:正则就是用来描述一类事物的规则.(在Python中)它内嵌在Python中,并通过 r ...