相关文章推荐
温暖的便当  ·  大“跨界”演绎莎翁经典:黄梅戏《仲夏夜之梦》 ...·  9 月前    · 
乖乖的骆驼  ·  政策法规--深圳市工业和信息化局·  10 月前    · 
飘逸的蚂蚁  ·  任贤齐:落魄时靠借钱度日,成名后带妻儿和父母 ...·  10 月前    · 
健身的键盘  ·  2023年度全国注册环保工程师执业资格考试报 ...·  11 月前    · 
犯傻的毛衣  ·  Aflodit_百度百科·  11 月前    · 
小百科  ›  自定义Mybatis-plus插件(限制最大查询数量)-天翼云
云计算 运营商 天翼云 天翼
行走的甘蔗
10 月前

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
查看全部活动
热门活动
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 一键部署Llama3大模型学习机 0代码一键部署,预装最新主流大模型Llama3与StableDiffusion
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 云主机特惠 HOT 多款云主机新老同享,满足您的上云需求!
  • 推荐有礼 推荐新人实名注册有好礼,下单更得千元代金券!
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城 进入云市场
办公协同
  • WPS云文档 EMM手机管家 智能商业平台 SSL证书 新域名服务 翼电子教室 翼智慧显示一体化解决方案 税务风控云 翼云智眼安消一体化解决方案 翼信息化运维服务 翼微信营销解决方案 翼视频云归档解决方案 云管家2.0 智慧工厂_生产流程管理解决方案 全栈混合云敏捷版(软件) 全栈混合云敏捷版(一体机)

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云技术合作伙伴
  • 天翼云OpenAPI中心 天翼云EasyCoding平台
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云培训认证
  • 天翼云学堂 天翼云市场商学院
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云合作计划
  • 央企云合作计划
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴 天翼云甄选商城合作伙伴
天翼云东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
资源与工具
  • 天翼云OpenAPI EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂 天翼云认证

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • OpenAPI中心 客户支持计划 专家技术服务

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云 天翼云4.0 天翼云APP 全球基础设施 分析师和白皮书 天翼云·创新直播间 2024智算云生态大会 2023云生态大会 2022云生态大会 天翼云中国行 支持与服务 了解天翼云
  • 站点切换
    • 中国站
  • 文档
  • 控制中心
  • 备案
  • 管理中心

自定义Mybatis-plus插件(限制最大查询数量)

首页 知识中心 数据库 文章详情页

自定义Mybatis-plus插件(限制最大查询数量)

2023-07-27 06:01:17 阅读次数:39

java, mysql

自定义Mybatis-plus插件(限制最大查询数量)

​ 一次查询如果结果返回太多(1万或更多),往往会导致系统性能下降,有时更会内存不足,影响系统稳定性,故需要做限制。

1.经分析最后决定,应限制一次查询返回的最大结果数量不应该超出1万,对于一次返回结果大于限制的时候应该抛出异常,而不应该截取(limit 10000)最大结果(结果需求不匹配)。

2.利用mybatis拦截器技术,统一拦截sql,并真对大结果的查询先做一次count查询。

1.1 定义拦截器PreCheckBigQueryInnerInterceptor

public class PreCheckBigQueryInnerInterceptor implements InnerInterceptor {}
1.2 重写willDoQuery方法
 public boolean willDoQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        // 解析sql
        Statement stmt = CCJSqlParserUtil.parse(boundSql.getSql());
        if (stmt instanceof Select) {
            PlainSelect selectStmt = (PlainSelect) ((Select) stmt).getSelectBody();
            if (Objects.nonNull(selectStmt.getLimit())) {
                //包含limit查询
                return true;
            for (SelectItem selectItem : selectStmt.getSelectItems()) {
                //计数查询 count();
                SelectExpressionItem selectExpressionItem = (SelectExpressionItem) selectItem;
                if (selectExpressionItem.getExpression() instanceof Function) {
                    //包含function查询
                    return true;
            Long aLong = doQueryCount(executor, ms, parameter, rowBounds, resultHandler, boundSql);
            if (aLong == 0L) {
                return false;
            if (aLong > 20) {
                throw new RuntimeException("单个查询结果大于20条!!!");
        return true;
1.3 代码解析
1.3.1 利用CCJSqlParserUtil解析sql,并判断sql类型,只对Select的SQL拦击.
1.3.2 对于已有limit的sql查询,直接放行.
1.3.3 对于包含function查询(例如count(1)计算,max()...),直接放行.
1.3.4 否则判断为大结果查询,执行(doQueryCount)与查询数量.
1.3.5 对于大于指定数量的结果,抛出异常.
1.4 定义doQueryCount方法
private Long doQueryCount(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        MappedStatement countMs = buildAutoCountMappedStatement(ms);
        String countSqlStr = autoCountSql(true, boundSql.getSql());
        PluginUtils.MPBoundSql mpBoundSql = PluginUtils.mpBoundSql(boundSql);
        BoundSql countSql = new BoundSql(countMs.getConfiguration(), countSqlStr, mpBoundSql.parameterMappings(), parameter);
        PluginUtils.setAdditionalParameter(countSql, mpBoundSql.additionalParameters());
        CacheKey cacheKey = executor.createCacheKey(countMs, parameter, rowBounds, countSql);
        Object result = executor.query(countMs, parameter, rowBounds, resultHandler, cacheKey, countSql).get(0);
        System.out.println(result);
        return (result == null ? 0L : Long.parseLong(result.toString()));
代码解读:参考PaginationInnerInterceptor(mybatis-plus)分页插件
1.4.1:构造MappedStatement对象buildAutoCountMappedStatement(ms),MappedStatement相当于一个存储 SQL 语句、输入参数和输出结果映射等信息的封装体,它对应一条 SQL 语句,并包含了该 SQL 语句执行所需的所有信息。如下代码
<mapper namespace="com.example.UserMapper">
   <select id="selectAllUsers" resultType="com.example.User">
       SELECT * FROM user
   </select>
</mapper>

注意:必须重新构造,不能直接使用入参中的ms

1.4.2:autoCountSql(true, boundSql.getSql()) 定义并优化计数查询语句
String.format("SELECT COUNT(1) FROM (%s) TOTAL", originalSql);
1.4.3: 执行查询executor.query

1.1 注册拦截器PreCheckBigQueryInnerInterceptor

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//分页插件(Mybatis-plus)
    interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());//防止全表更新(Mybatis-plus)
    interceptor.addInnerInterceptor(new PreCheckBigQueryInnerInterceptor());//防止全表查询(自定义插件)
    return interceptor;

知识小结:

  • MybatisPlusInterceptor
  • public class MybatisPlusInterceptor implements Interceptor {
        @Setter
        private List<InnerInterceptor> interceptors = new ArrayList<>();
    

    ​ 他是基于mybatis的Interceptor接口做的拦截器,上文中我们 注册拦截器PreCheckBigQueryInnerInterceptor的拦截器其实添加到MybatisPlusInterceptor.interceptors集合中。

  • 为啥重写willDoQuery见代码而不是beforeQuery
  •  public Object intercept(Invocation invocation) throws Throwable {
           ......
                    for (InnerInterceptor query : interceptors) {
                        if (!query.willDoQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql)) {
                            return Collections.emptyList();
                        query.beforeQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql);
         ......
            return invocation.proceed();
    

    2.1 willDoQuery先于beforeQuery方法,且一定会执行

    版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://www.cnblogs.com/jinliang374003909/p/17333060.html,作者:爱我-中华,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

    上一篇: MySQL日常巡检和监控

    下一篇: JDBC的CRUD操作之查询数据操作

    相关文章

    2024-07-12 07:06:53

    mybatis 实现批量多条件的查询【案例+代码】

    mybatis 实现批量多条件的查询【案例+代码】

    2024-07-12 07:06:53
    mybatis mysql 2024-07-12 07:06:42

    java处理pdf代码

    java处理pdf代码

    2024-07-12 07:06:42
    2024-07-12 07:02:30

    java.lang.NoClassDefFoundError: org/apache/log4j/Level的解决方案

    java.lang.NoClassDefFoundError: org/apache/log4j/Level的解决方案

    2024-07-12 07:02:30
    2024-07-12 07:02:30

    Failed to bind properties under ‘logging.level‘ to java.util.Map java.lang.String, java.lang.String

    Failed to bind properties under ‘logging.level‘ to java.util.Map java.lang.String, java.lang.String

    2024-07-12 07:02:30
    2024-07-11 09:40:42

    OSCP-Fail(rsync、fail2ban提权)

    OSCP-Fail(rsync、fail2ban提权)

    2024-07-11 09:40:42
    linux 2024-07-11 09:38:12

    用户拦截器【项目 商场】

    拦截器:首先将所有的请求统一拦截到拦截器中,可以在拦截器中来定义过滤的规则没如果不满足系统的设置的过滤规则,统一的处理是重新去打开login.html页面(重定向和转发),推荐使用重定向。

    2024-07-11 09:38:12
    springboot 2024-07-11 09:38:12

    获取省市区的名称【项目 商城】

    获取省市区的名称【项目 商城】

    2024-07-11 09:38:12
    springboot 2024-07-08 08:10:59

    jsp文件的请求是如何被服务器的JSP容器转换成静态网页的

    jsp文件的请求是如何被服务器的JSP容器转换成静态网页的

    2024-07-08 08:10:59
    2024-07-04 09:22:43

    修改密码【项目 商城】

    修改密码【项目 商城】

    2024-07-04 09:22:43
    springboot 2024-07-04 09:22:43

    上传头像【项目 商城】

    上传头像【项目 商城】

    2024-07-04 09:22:43
    springboot
    查看更多
    推荐标签

    作者介绍

    天翼云小翼
    天翼云用户

    文章

    22717

    阅读量

    2217597

    查看更多

    最新文章

    MySQL常用函数汇总

    2024-07-01 01:32:51

    mysql备份与恢复

    2024-06-28 06:18:44

    字符串数值的比较 java

    2024-06-28 06:18:15

    go 通过sql操作mysql

    2024-06-28 06:18:10

    go-mysql-server 新版本发布

    2024-06-28 06:18:10

    mysql函数

    2024-06-28 06:18:03

    查看更多

    热门文章

    Windows下使用批处理实现启动关闭mysql

    2023-04-24 11:27:05

    Docker容器mysql创建表报错:Table ‘mybatis_plus.USER‘ doesn‘t exist 问题解决

    2023-04-27 08:05:47

    cdh安装到scm-server的mysql报错处理

    2023-04-28 02:38:44

    Nacos数据持久化到MySQL

    2023-05-12 07:20:56

    python学习——使用MySQL

    2023-04-27 07:57:16

    MySQL的间隙锁

    2023-05-12 07:20:56

    查看更多

    热门标签

    mysql MySQL redis oracle python linux leetcode Oracle
    查看更多

    相关产品

    弹性云主机

    随时自助获取、弹性伸缩的云服务器资源

    天翼云电脑(公众版)

    便捷、安全、高效的云电脑服务

    对象存储

    高品质、低成本的云上存储服务

    云硬盘

    为云上计算资源提供持久性块存储

    查看更多

    随机文章

    字符串截取

    Lc3-无重复字符的最长子串

    千万别手欠执行stop slave

    学习 MySQL 中的 SQL_SMALL_RESULT 关键字

    java面试知识点整理之数据结构算法(待完善)

    topK问题

    • 7*24小时售后
    • 无忧退款
    • 免费备案
    • 专家服务
    售前咨询热线
    400-810-9889转1
    • 天翼云APP
      天翼云APP
     
    推荐文章
    温暖的便当  ·  大“跨界”演绎莎翁经典:黄梅戏《仲夏夜之梦》上演-新华网
    9 月前
    乖乖的骆驼  ·  政策法规--深圳市工业和信息化局
    10 月前
    飘逸的蚂蚁  ·  任贤齐:落魄时靠借钱度日,成名后带妻儿和父母回湖北武汉寻根_ ...
    10 月前
    健身的键盘  ·  2023年度全国注册环保工程师执业资格考试报考简章_ 考试信息_ ...
    11 月前
    犯傻的毛衣  ·  Aflodit_百度百科
    11 月前
    今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
    删除内容请联系邮箱 2879853325@qq.com
    小百科 - 百科知识指南
    © 2024 ~ 沪ICP备11025650号