pageHelper沒有正確分頁,sql拼接多加limit等引數。
pageHelper沒有正確分頁,sql拼接多加limit等引數。
背景:
日常敲程式碼,發現用了pageHelper真的方便,尤其是使用了pageInfo這個類,不用自己寫工具類了,直接將所有的頁碼資訊封裝到PageInfo裡,但是,使用過程中發生了sql語法錯誤,檢視之後發現sql語句又多加了limit或者在不應該排序的地方加了一個排序的規則。而且專案有的時候正常有的時候錯誤。
-
不分頁,查出多少條資料給出多少條:
沒有分頁標誌。
-
多次重新整理頁面
出現這個,明明沒加limit,這個mapper也沒有分頁。
- 多次重新整理後查出來的資料也不正確了。庫裡明明有12條資料,結果查出來5條。
有時候正確有時候錯誤。
解決方案
檢視自己的寫語句,既然不分頁,先考慮是不是程式碼沒有寫對。
@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"; }
乍一看,其實沒有問題,但是讀到官網的這一條:
順序寫錯了。。。糾錯老長時間,修改下順序就行了。
當然,按照官網說的,使用PageHelper方法有可能產生執行緒安全問題,其實這就是因為pageHelper沒有跟在mybatis查詢方法之後導致的執行緒安全。具體可以檢視官網。
官網的解釋
PageHelper
方法使用了靜態的 ThreadLocal
引數,分頁引數和執行緒是繫結的。
只要你可以保證在 PageHelper
方法呼叫後緊跟 MyBatis 查詢方法,這就是安全的。因為 PageHelper
在 finally
程式碼段中自動清除了 ThreadLocal
儲存的物件。
如果程式碼在進入 Executor
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的方法。