• 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) {
    
        }
    }
  • 相关阅读:
    记录JavaScript原型和原型链复习笔记
    记录浏览器渲染流程解析
    记录前端路由 hash 与 history 差异
    作用域&变量提升&闭包题目及内容解答
    记录JS原型链
    记录JS精粹,原型链继承和构造函数继承的 “毛病”
    虚拟DOM的理解与总结
    Vite+TS项目:论如何便捷的使用pinia
    Redis知识总结
    JVM家庭成员盘点及各自职能介绍 https://mp.weixin.qq.com/s/TkGZ5fMTOdr9ABNf_xllnw
  • 原文地址:https://www.cnblogs.com/Springmoon-venn/p/7040318.html
Copyright © 2020-2023  润新知