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
前發生異常,就會導致線程不可用,這屬於人為的 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的方法。