• pageHelper没有正确分页,sql拼接多加limit等参数。


    pageHelper没有正确分页,sql拼接多加limit等参数。

    背景:

    日常敲代码,发现用了pageHelper真的方便,尤其是使用了pageInfo这个类,不用自己写工具类了,直接将所有的页码信息封装到PageInfo里,但是,使用过程中发生了sql语法错误,查看之后发现sql语句又多加了limit或者在不应该排序的地方加了一个排序的规则。而且项目有的时候正常有的时候错误。

    1. 不分页,查出多少条数据给出多少条:

      image-20200729165321936

      没有分页标志。

    2. 多次刷新页面

    image-20200729165413035

    出现这个,明明没加limit,这个mapper也没有分页。

    1. 多次刷新后查出来的数据也不正确了。库里明明有12条数据,结果查出来5条。

    image-20200729165543921

    image-20200729165609883

    有时候正确有时候错误。

    解决方案

    查看自己的写语句,既然不分页,先考虑是不是代码没有写对。

    @GetMapping("/types/{id}")
    public String types(Model model, @RequestParam(value = "page",required = false) Integer pageNum, @PathVariable Long id) {
        //找出所有的type
        List<TypeIndexDto> types = typeService.listType2Index();
        if (pageNum==null){
            pageNum=1;
        }
        if (id == -1) {
            id = types.get(0).getId();
        }
        //根据typeId查询所属博客并罗列出来
        List<BlogIndexDto> blogIndexDtos = blogService.selectBlogByTypeId(id);
        PageHelper.startPage(pageNum,5);
        PageInfo<BlogIndexDto> pageInfo = new PageInfo<>(blogIndexDtos);
        model.addAttribute("types", types);
        model.addAttribute("page", pageInfo);
        model.addAttribute("activeType", id);
        return "types";
    }
    

    乍一看,其实没有问题,但是读到官网的这一条:

    image-20200729165826075

    顺序写错了。。。纠错老长时间,修改下顺序就行了。

    当然,按照官网说的,使用PageHelper方法有可能产生线程安全问题,其实这就是因为pageHelper没有跟在mybatis查询方法之后导致的线程安全。具体可以查看官网。

    官网的解释

    PageHelper 方法使用了静态的 ThreadLocal 参数,分页参数和线程是绑定的。

    只要你可以保证在 PageHelper 方法调用后紧跟 MyBatis 查询方法,这就是安全的。因为 PageHelperfinally 代码段中自动清除了 ThreadLocal 存储的对象。

    如果代码在进入 Executor 前发生异常,就会导致线程不可用,这属于人为的 Bug(例如接口方法和 XML 中的不匹配,导致找不到 MappedStatement 时), 这种情况由于线程不可用,也不会导致 ThreadLocal 参数被错误的使用。

    但是如果你写出下面这样的代码,就是不安全的用法:

    PageHelper.startPage(1, 10);
    List<User> list;
    if(param1 != null){
        list = userMapper.selectIf(param1);
    } else {
        list = new ArrayList<User>();
    }
    

    这种情况下由于 param1 存在 null 的情况,就会导致 PageHelper 生产了一个分页参数,但是没有被消费,这个参数就会一直保留在这个线程上。当这个线程再次被使用时,就可能导致不该分页的方法去消费这个分页参数,这就产生了莫名其妙的分页。

    上面这个代码,应该写成下面这个样子:

    List<User> list;
    if(param1 != null){
        PageHelper.startPage(1, 10);
        list = userMapper.selectIf(param1);
    } else {
        list = new ArrayList<User>();
    }
    

    这种写法就能保证安全。

    如果你对此不放心,你可以手动清理 ThreadLocal 存储的分页参数,可以像下面这样使用:

    List<User> list;
    if(param1 != null){
        PageHelper.startPage(1, 10);
        try{
            list = userMapper.selectAll();
        } finally {
            PageHelper.clearPage();
        }
    } else {
        list = new ArrayList<User>();
    }
    

    这么写很不好看,而且没有必要。

    总结

    在改错的过程中,一度怀疑是pageHelper出了问题,想重写分页工具类,经过排错后发现,根本不用,只要自己按照官网的来就可以避免不安全的调用pageHelper的方法。

  • 相关阅读:
    菜鸟合作伙伴日志接入规范之C#实现
    使用JS在textarea在光标处插入内容
    ASP.NET MVC API 接口验证
    CSS3 grayscale滤镜+SVG使图片变黑白实例页面
    .NET MVC 获取 当前请求的 控制器/视图/区域 的名字
    asp.net 后台获取flv视频地址进行播放【转】
    实现输出h264直播流的rtmp服务器 flash直播服务器【转】
    如何实现一个c/s模式的flv视频点播系统
    视频流服务器配置[windows平台][转]
    小计
  • 原文地址:https://www.cnblogs.com/chenyameng/p/13398212.html
Copyright © 2020-2023  润新知