最近做的項目,使用了Spring的PageHelper插件,發現了一個奇怪的問題,經常會給SQL無緣無故的增加Limit語句,經過調查,發現原因是沒有安全的使用PageHelper插件,我們先來看一個例子:
PageHelper.startPage(pageable.getPageNumber(), pageable.getPageSize());
PageInfo<CommMROrderDetailEntity> list = null;
if (condition.getCustomerIdListForUser() != null && condition.getCustomerIdListForUser().size() > 0) {
list = new PageInfo<>(ocs010Mapper.findOrderList(condition)); //分頁查詢語句
} else {
list = new PageInfo<>(new ArrayList<CommMROrderDetailEntity>());
list.setPageNum(0);
list.setPageSize(1);
list.setTotal(0);
}
在這個例子中,PageHelper.startPage就屬於明顯的不安全調用,因爲PageHelper的原理是,在PageHelper.startPage調用時,會給全局對象LOCAL_PAGE設值,然後通過Spring的攔截器攔截每個SQL語句,如果LOCAL_PAGE有值,則給該SQL增加Limit,並調用clearPage方法清除LOCAL_PAGE的值;
但是上面的代碼,其分頁查詢語句有可能因爲if的條件的不滿足沒有執行,所以在程序執行結束時,PageHelper.startPage已經執行,LOCAL_PAGE的值已經設置
當線程池再次分配該線程執行其他程序時,可能會在該程序的第一個SQL上增加了Limit語句。
解決該問題的方法是,要絕對保證PageHelper.startPage和分頁查詢語句之間不要有任何其他語句,或者在程序結束時增加PageHelper.clearPage();的調用,例:
PageInfo<CommMROrderDetailEntity> list = null;
if (condition.getCustomerIdListForUser() != null && condition.getCustomerIdListForUser().size() > 0) {
PageHelper.startPage(pageable.getPageNumber(), pageable.getPageSize());
list = new PageInfo<>(ocs010Mapper.findOrderList(condition));//分頁查詢語句
} else {
list = new PageInfo<>(new ArrayList<CommMROrderDetailEntity>());
list.setPageNum(0);
list.setPageSize(1);
list.setTotal(0);
}
或者
PageHelper.startPage(pageable.getPageNumber(), pageable.getPageSize());
PageInfo<CommMROrderDetailEntity> list = null;
if (condition.getCustomerIdListForUser() != null && condition.getCustomerIdListForUser().size() > 0) {
list = new PageInfo<>(ocs010Mapper.findOrderList(condition));
} else {
list = new PageInfo<>(new ArrayList<CommMROrderDetailEntity>());
list.setPageNum(0);
list.setPageSize(1);
list.setTotal(0);
}
PageHelper.clearPage();