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的方法。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM