SQL多出limit ?導致報錯
阿新 • • 發佈:2022-12-02
PgageHelper使用不當導致sql報錯
1、發現介面呼叫異常
檢視原因發現出現多個limit導致報錯
org.springframework.jdbc.BadSqlGrammarException: select * from table where xx order by cl.plan_live_time asc limit 20 LIMIT ?
2、排查 業務sql
select * from table where xx order by cl.plan_live_time asc limit 20
檢視業務sql沒有問題,也不會存在拼接問題,懷疑元件幫忙做了新增limit ?這件事
3、發現 PageHelper使用不當會造成該問題
PageHelper.startPage(pageInfoVO.getPage(), pageInfoVO.getPageSize());
底層會呼叫下面的方法:
public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) { Page<E> page = new Page(pageNum, pageSize, count); page.setReasonable(reasonable); page.setPageSizeZero(pageSizeZero); Page<E> oldPage = getLocalPage(); if (oldPage != null && oldPage.isOrderByOnly()) { page.setOrderBy(oldPage.getOrderBy()); } setLocalPage(page); return page; }
呼叫setLocalPage(page);
public abstract class PageMethod { protected static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal(); protected static boolean DEFAULT_COUNT = true; public PageMethod() { } protected static void setLocalPage(Page page) { LOCAL_PAGE.set(page); } public static <T> Page<T> getLocalPage() { return (Page)LOCAL_PAGE.get(); } public static void clearPage() { LOCAL_PAGE.remove(); }
Springboot 中interceptor會攔截PageHelper做sql增強處理,如果PageHelper中含有Page分頁引數,則會新增limit ?
1、setLocalPage後,變數和執行緒進行繫結,在上下文中環境中都可能存在PageHelper中設定的**Page**分頁引數,後面的sql可能會新增limit ?。
2、ThreadLocal 中的ThreadLocalMap中的key是弱引用,發生GC時會被回收。如果其他請求分配到了此執行緒時未發生gc,則新請求也會出現此問題。
4、解決方式
在需要執行分頁查詢的sql前,開啟PageHelper分頁,執行完後清空PageHelper.clearPage()就是刪除之之前在**ThreadLocalMap**中的**Page**
PageHelper.startPage(pageDTO.getPage(), pageDTO.getPageSize()); //分頁sql程式碼 ...... //清理PageHelper可能自動新增limit導致分頁bug PageHelper.clearPage();