很多人都知道PageHelper怎麼使用,如果不知道在百度搜一下也會出現很多結果。
可是在項目裏引入了PageHelper,很少有人知道怎麼不使用它。
如果你在查看sql報錯,發現自己的代碼中使用的查詢sql被無緣無故添加了“PageHelper”,是不是該想知道該如何不使用PageHelper呢?
問題:
在項目中使用了pagehelper,總是莫名其妙的出現sql報警,由於使用了LIMIT ?導致的limit重複或是在“;”多了“LIMIT ?”。
分析:
1.只會在使用PageHelper之後纔會在sql中自動添加LIMIT ?,初步定位爲pageHelper使用錯誤。
2.查看pageHelper源碼,發現使用了 PageInterceptor 過濾器。只有在執行sql查詢的時候纔會執行。
3.當在方法中添加了 PageHelper.startPage(curPage, perPage); 但是在後面沒有使用到,就會被遺留到該線程下一次執行sql查詢。
4.由於tomcat使用線程池管理,所以,下一次複用該線程的時候就可能存在問題。
驗證:
(前提:要儘量全的打印日誌,其中必須包括線程號)
1.寫兩個controller,第一個controller裏面只有PageHelper.startPage(curPage, perPage); 第二個controller只有查詢sql,並且改sql包含limit (包含了limit的sql如果被添加LIMIT ?後會報異常,方便跟蹤)。
2.啓動程序,第一次調用第一個controller了,記錄執行線程號。
3.不斷的刷新第二個controller,直到報異常。查看報異常線程號。
3.驗證兩個線程號是不是同一個線程
再次驗證:
根據上述推斷查找線上日誌。
1.查找到報異常日誌所在服務器,以及相應的request_id。(request_id:是每個請求唯一的序列號,以識別該請求的所有處理過程)
2.根據request_id到相應服務器查找對應的線程號,例如此處爲“http-nio-8311-exec-9”
3.根據線程號和request_id查找該請求之前的請求處理。
cat xinche-deal-agency-manager-2019-07-02.log | grep 'http-nio-8311-exec-9' | grep -B100 'ed7b53fb-d08f-44ad-8e7e-e4e955c5927c'
4.定位到緊上一次處理的類和方法,分析該方法,查找是否存在寫了PageHelper.startPage(curPage, perPage); 但沒有執行的情況。
例如:
Int deptId = getDeptId();
PageHelper.startPage(1,10);
List<Object1> objs = null;
If(deptId == 1){
objs = mapper.getObjs1();
}else{
List<Object2> list = service.getObject2s();
If(list.size() > 0){
objs = mapper.getObjs2();
}else{
objs = new ArrayList();
}
}
修改:
1.增加filter
@WebFilter()
public class CommonFilter implements Filter{
/* (non-Javadoc)
* @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(request, response);
//清空pagehelper
PageHelper.clearPage();
}
/* (non-Javadoc)
* @see javax.servlet.Filter#destroy()
*/
@Override
public void destroy() {
// TODO Auto-generated method stub
}
}
2.修改上面的方法
Int deptId = getDeptId();
List<Object1> objs = null;
If(deptId == 1){
PageHelper.startPage(1,10);
objs = mapper.getObjs1();
}else{
List<Object2> list = service.getObject2s();
If(list.size() > 0){
PageHelper.startPage(1,10);
objs = mapper.getObjs2();
}else{
objs = new ArrayList();
}
}
修改原因:
1.將使用不當的方法進行修改,規範代碼及正確使用PageHelper.startPage(1,10);
2.對於所有請求使用filter處理,以免有使用出錯之處。
3.對於異步任務或是kafka,使用filter並不能處理,將錯誤方法修改更正即可。