mybatis拦截器案例之获取结果集总条数

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

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

由于在项目搭建的时候,是没有考虑数据量比较大(结果集数量大于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) {

    }
}
时间: 2024-10-31 10:28:49

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

mybatis拦截器

业务需求:由于公司业务需要在所有的sql的增删改查中必须包含officeId,业务以officeId做隔离.因此做了一个Mybatis的的过去器.通过拦截sql处理的过程来判断接口sql是否包含officeId,如果不包含则添加officeId.@NoNeedOffice的注解可以添加在Dao的接口类或方法上.用于标识不需要处理的接口. package com.example.springcloud.provider; import com.example.springcloud.provide

Mybatis拦截器介绍及分页插件

1.1    目录 1.1 目录 1.2 前言 1.3 Interceptor接口 1.4 注册拦截器 1.5 Mybatis可拦截的方法 1.6 利用拦截器进行分页 1.2     前言 拦截器的一个作用就是我们可以拦截某些方法的调用,我们可以选择在这些被拦截的方法执行前后加上某些逻辑,也可以在执行这些被拦截的方法时执行自己的逻辑而不再执行被拦截的方法.Mybatis拦截器设计的一个初衷就是为了供用户在某些时候可以实现自己的逻辑而不必去动Mybatis固有的逻辑.打个比方,对于Executor

Mybatis拦截器介绍

拦截器的一个作用就是我们可以拦截某些方法的调用,我们可以选择在这些被拦截的方法执行前后加上某些逻辑,也可以在执行这些被拦截的方法时执行自己的逻辑而不再执行被拦截的方法.Mybatis拦截器设计的一个初衷就是为了供用户在某些时候可以实现自己的逻辑而不必去动Mybatis固有的逻辑.打个比方,对于Executor,Mybatis中有几种实现:BatchExecutor.ReuseExecutor.SimpleExecutor和CachingExecutor.这个时候如果你觉得这几种实现对于Execu

Mybatis拦截器实现分页

本文介绍使用Mybatis拦截器,实现分页:并且在dao层,直接返回自定义的分页对象. 最终dao层结果: public interface ModelMapper { Page<Model> pageByConditions(RowBounds rowBounds, Model record); } 接下来一步一步来实现分页. 一.创建Page对象: public class Page<T> extends PageList<T> { private int page

Mybatis 拦截器(二)

Mybatis拦截器介绍 拦截器的一个作用就是我们可以拦截某些方法的调用,我们可以选择在这些被拦截的方法执行前后加上某些逻辑,也可以在执行这些被拦截的方法时执行自己的逻辑而不再执行被拦截的方法.Mybatis拦截器设计的一个初衷就是为了供用户在某些时候可以实现自己的逻辑而不必去动Mybatis固有的逻辑.打个比方,对于Executor,Mybatis中有几种实现:BatchExecutor.ReuseExecutor.SimpleExecutor和CachingExecutor.这个时候如果你觉

mybatis拦截器使用

[toc] mybatis拦截器入门 mybatis 拦截器接口Interceptor Interceptor接口,我们通过这个接口可以自定义我们自己的拦截器,从而实现在拦截的时候写上我们自己的一些逻辑.该接口提供了三个方法, 接口介绍: intercept方法: intercept方法是在进行拦截的时候要执行的方法. plugin方法: 该方法是拦截器用于封装目标对象的,通过该方法我们可以返回目标对象本身,也可以返回一个它的代理. setProperties方法: mybatis配置文件中co

Mybatis拦截器源码深度解析

目录: 一. 建立拦截器链1. 创建对象2. 建立配置文件3. 加载拦截器链二. 方法调用解析1. 对请求对象进行拦截器包装2. 执行调用三. 小结 Mybatis拦截器 可以帮助我们在执行sql语句过程中增加插件以实现一些通用的逻辑,比如对查询sql分页.数据权限处理等. 允许使用插件拦截的方法调用包括: - Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)

玩转SpringBoot之整合Mybatis拦截器对数据库水平分表

利用Mybatis拦截器对数据库水平分表 需求描述 当数据量比较多时,放在一个表中的时候会影响查询效率:或者数据的时效性只是当月有效的时候:这时我们就会涉及到数据库的分表操作了.当然,你也可以使用比较完善的第三方组件:sharding-jdbc来实现:但是你使用后会发现,貌似对oracle的兼容性不是很好.所以最后我还是决定使用Mybatis拦截器对数据库进行水平分表. 为什么要选用Mybatis拦截器 拦截器:我们可以拦截某些方法的调用,我们可以选择在这些被拦截的方法执行前后加上某些逻辑,也可

【Mybatis】1、Mybatis拦截器

MyBatis拦截器原理探究 http://www.cnblogs.com/fangjian0423/p/mybatis-interceptor.html MyBatis 拦截器 (实现分页功能) http://www.cnblogs.com/jethypc/p/5149183.html 由浅入深分析mybatis通过动态代理实现拦截器(插件)的原理 http://zhangbo-peipei-163-com.iteye.com/blog/2033832 使用方法 https://github.