请选择 进入手机版 | 继续访问电脑版

石家庄老站长

点击联系客服
客服QQ: 客服微信:
 找回密码
 立即注册
查看: 3|回复: 0

[Java Core]-在我同事的选择页面上找到了3000W个数据

[复制链接]

1

主题

1

帖子

-7

积分

限制会员

积分
-7
发表于 2021-7-21 15:24:16 | 显示全部楼层 |阅读模式
你好,我是大明哥

有一天,我在工作中听着Vicotry,愉快地拍打着hello  world。感觉就像我写的代码可以征服世界一样。突然云飞叫了我们服务器OOM中的一台,让我去看看,感觉就像XXX一样。你也知道。(威廉莎士比亚,北上广深)。

去运营室,登录服务器,查看日志,一顿饭操作猛如老虎,看清单对象600MB(原谅我们的服务器List,运维比较吝啬,给1C2G的服务器),检查当时的SQL语句,检查我的乖乖,将近4000w的数据,我的第一感觉是,还有什么业务在导出大量数据。但是,我们所有的Excel导出数据都经过验证,如果数据量超过5w,就会在后台成批导出。(所以有时候要庆幸服务器low。由于服务器low,需要多种优化。所有大容量数据操作都要想办法优化。所以我们的应用程序会做各种有趣的骚操作,以后有机会分享。)没有控制吗?查看日志,没有发现大量数据量的Excel导出,可以断定是没有分页的地方。查看代码,您可以在if语句中找到坑,如下所示:

page  helper  . start  page(query  dto  . get  page(),query  dto  . get  limit());

PageUserDTO  page

If  (isWitchF
lag()) {
    page = userMapper.selectUserList(queryDTO);
}

isWitchFlag() :

    private boolean isWitchFlag() {
        String witchFlag = systemConfigMapper.selectSwitchFlag("key");
        return "1".equals(witchFlag);
    }

对 PageHelper 不是很熟悉的人一定不知道这个坑在哪里!在 PageHelper 使用文档(https://pagehelper.github.io/faq/)中第一句就阐述了:



只有紧跟在 PageHelper.startPage 方法后的第一个 Mybatis 的查询(Select)方法会被分页。。请注意关键词紧跟。为什么要紧跟呢?因为 PageHelper 的分页原理使用了 ThreadLocal,他的分页参数和线程是绑定在一起的,当我们执行 PageHelper.startPage() 语句时,他会将分页参数绑定到 ThreadLocal 中:



setLocalPage():



在拦截器 PageInterceptor 中,最后的 finally 会将 Page 分页信息给 remove 掉:





所以,上面那段代码的分页信息被 if 语句中的 select 查询语句给消耗掉了,下面真正需要分页的语句当然就不会执行分页信息了。怎么解决?两种方案:

  • 治标不治本:将 PageHelper.startPage() 挪到 if 语句里面,让真正的查询语句紧挨着它。这种方案不治本的原因在于,如果又有小伙伴不知道这个坑,有可能又会踩。
  • 治标治本:使用 Function Lamdba 表达式。
    使用 Function Lamdba 来将 PageHelper.startPage() 与分页查询语句紧挨在一起,规避掉这个坑

    首先我们需要定义一个 PageHelperTool,该 PageHelperTool 是封装了分页语句:

    @Builder
    public class PageHelperToolP,R> {
        private final FunctionP, PageR>> pageFunction;
        public PageR> getPageInfo(P request) {
            PageHelper.startPage(((PageRequest)request).getPage(),((PageRequest)request).getLimit());
            return pageFunction.apply(request);
        }
    }

    然后将分页的地方全部替换为 PageHelperTool 就可以了:

            PageUserDTO> page;
            if (isWitchFlag()) {
                PageHelperToolQueryDTO,UserDTO> pageHelperTool = PageHelperTool.QueryDTO,UserDTO>builder()
                                                                .pageFunction(userMapper::selectUserList)
                                                                .build();
                
                page = pageHelperTool.getPageInfo(queryDTO);
            }

    这样就可以彻底解决因误用 PageHelper 导致分页失效的问题了。

    最后一句话:注意看文档啊!!!!!!
  • 回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|无图版|手机版|小黑屋|石家庄@IT精英团

    GMT+8, 2021-8-5 12:13 , Processed in 0.171601 second(s), 27 queries .

    Powered by Discuz! X3.4

    © 2001-2021 Comsenz Inc.

    快速回复 返回顶部 返回列表