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) { }
}
mybatis拦截器案例之获取结果集总条数的更多相关文章
- Mybatis拦截器(六)
拦截器的作用就是我们可以拦截某些方法的调用,在目标方法前后加上我们自己逻辑. Mybatis拦截器设计的一个初衷是为了供用户在某些时候可以实现自己的逻辑而不必去动Mybatis固有的逻辑. Mybat ...
- Mybatis拦截器介绍
拦截器的一个作用就是我们可以拦截某些方法的调用,我们可以选择在这些被拦截的方法执行前后加上某些逻辑,也可以在执行这些被拦截的方法时执行自己的逻辑而不再执行被拦截的方法.Mybatis拦截器设计的一个初 ...
- Mybatis拦截器实现分页
本文介绍使用Mybatis拦截器,实现分页:并且在dao层,直接返回自定义的分页对象. 最终dao层结果: public interface ModelMapper { Page<Model&g ...
- 数据权限管理中心 - 基于mybatis拦截器实现
数据权限管理中心 由于公司大部分项目都是使用mybatis,也是使用mybatis的拦截器进行分页处理,所以技术上也直接选择从拦截器入手 需求场景 第一种场景:行级数据处理 原sql: select ...
- 基于Spring和Mybatis拦截器实现数据库操作读写分离
首先需要配置好数据库的主从同步: 上一篇文章中有写到:https://www.cnblogs.com/xuyiqing/p/10647133.html 为什么要进行读写分离呢? 通常的Web应用大多数 ...
- 通过spring抽象路由数据源+MyBatis拦截器实现数据库自动读写分离
前言 之前使用的读写分离的方案是在mybatis中配置两个数据源,然后生成两个不同的SqlSessionTemplate然后手动去识别执行sql语句是操作主库还是从库.如下图所示: 好处是,你可以人为 ...
- spring boot 实现mybatis拦截器
spring boot 实现mybatis拦截器 项目是个报表系统,服务端是简单的Java web架构,直接在请求参数里面加了个query id参数,就是mybatis mapper的query id ...
- mybatis拦截器使用
目录 mybatis 拦截器接口Interceptor spring boot + mybatis整合 创建自己的拦截器MyInterceptor @Intercepts注解 mybatis拦截器入门 ...
- Mybatis拦截器介绍及分页插件
1.1 目录 1.1 目录 1.2 前言 1.3 Interceptor接口 1.4 注册拦截器 1.5 Mybatis可拦截的方法 1.6 利用拦截器进行分页 1.2 前言 拦截器的一 ...
随机推荐
- spring上下文快速获取方法
import org.springframework.beans.BeansException;import org.springframework.context.ApplicationContex ...
- Java_7.1 ArrayList应用点名器
1.ArrayList同样可以添加自定义的类 将学生类添加到ArrayList集合中,其中学生类包括学生姓名,年龄 自定义学生类 package demo1; public class Student ...
- connot connect to mysql 10061
根据我自己运行的情况,解决方法如下: 按windows+R, 输入services.msc查找服务,在服务与应用中找到MYsql服务,查看是否已启动.
- Aspose.Words五 MergeField
通过MegerField来循环,将数据保存到dataset的table中,dataset通过关联datarelation字段来指定主从表关系.模板中通过标签TableStart和TableEnd来框定 ...
- 地图调起URI API(通过连接直接调用百度地图)
网站:http://lbsyun.baidu.com/index.php?title=uri/api/web 地图调起URI API 百度地图URI API是为开发者提供直接调起百度地图产品(百度We ...
- 为什么说windows会死机,Linux不会死机
通常所说的死机是指操作没有响应了,但是操作系统的核心仍然在工作.在windows中,由于只有一个界面,没有响应就是死机了:而在Linux中可有tty1-tty7,死了一个开另外一个把死了的那个杀掉就可 ...
- PHP 根据两点的坐标计算之间的距离
define('PI',3.1415926535898); define('EARTH_RADIUS',6378.137); //计算范围,可以做搜索用户 function GetRange($lat ...
- hdu 5326(基础题) work
http://acm.hdu.edu.cn/showproblem.php?pid=5326 一道水题,题目大意是在公司里,给出n个员工和目标人数m,然后下面的n-1行是表示员工a管理b,问在这些员工 ...
- Linux系统和性能监控之CPU篇
Linux系统和性能监控之CPU篇 性能优化就是找到系统处理中的瓶颈以及去除这些的过程.本文由sanotes.net站长tonnyom在2009年8月翻译自Linux System and Perfo ...
- 758B Blown Garland
B. Blown Garland time limit per test 1 second memory limit per test 256 megabytes input standard inp ...