1. 程式人生 > 其它 >SQL多出limit ?導致報錯

SQL多出limit ?導致報錯

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();