背景
我們的springboot應用程式的持久層,是用jeecgboot框架生成的代碼,mybatisplus版本是3.1.2,
在一次對當前程式的sql性能優化時,我重寫了BaseMapper的selectPage方法,其中,為Wrapper<T>引數加上了id限制,以提高sql執行性能,
import com.baomidou.mybatisplus.core.mapper.BaseMapper; public interface SbhPlatOrderMapper extends BaseMapper<SbhPlatOrder> { @Override default IPage<SbhPlatOrder> selectPage(IPage<SbhPlatOrder> page, @Param(Constants.WRAPPER) Wrapper<SbhPlatOrder> queryWrapper){ PrePageDto prePageDto = selectCountCache(queryWrapper); page.setTotal(prePageDto.getRowCount()); if (prePageDto.getRowCount()>0) { if (queryWrapper instanceof LambdaQueryWrapper) { ((LambdaQueryWrapper<SbhPlatOrder>) queryWrapper).between(SbhPlatOrder::getId, prePageDto.getMinId(), prePageDto.getMaxId()); } else if (queryWrapper instanceof QueryWrapper) { ((QueryWrapper<SbhPlatOrder>) queryWrapper).lambda().between(SbhPlatOrder::getId, prePageDto.getMinId(), prePageDto.getMaxId()); } page.setRecords(selectPageList((page.getCurrent() - 1) * page.getSize(), page.getSize(), queryWrapper)); } return page; } @Cacheable(cacheNames = RedisConfig.SBH_PLAT_ORDER_COUNT_CACHE_KEY, key = "T(com.emax.zhenghe.common.util.security.MD5Util).md5Encode(#queryWrapper.customSqlSegment)") PrePageDto selectCountCache(@Param(Constants.WRAPPER) Wrapper<SbhPlatOrder> queryWrapper); ,,, }
問題描述
程式上線后運行了一段時間,后來,發現了一個問題,見下面日志截圖

原來呢,service類里呼叫這個分頁的方法里,并不是每次呼叫分頁時都new一個Wrapper物件,而是重復使用一個Wrapper物件, 所以,出現上圖的問題就不難理解了,
解決辦法 -Wrapper#getCustomSqlSegment
頭疼醫頭的方式,是修改service類里呼叫這個分頁的方法,每次呼叫分頁前都new一個Wrapper物件,
顯然,這樣解決問題只是一時,以后再有呼叫這個分頁的地方,依然會存在這個問題呀,
所以,我的解決辦法是利用 Wrapper#getCustomSqlSegment, 上面sql里重復出現的是 id BETWEEN,所以,修正的代碼如下:
// 外面呼叫處可能復用這個queryWrapper物件,所以,為避免重復追加條件,這里先做判讀再追加, if (!queryWrapper.getCustomSqlSegment().contains("id BETWEEN")) { if (queryWrapper instanceof LambdaQueryWrapper) { ((LambdaQueryWrapper<SbhPlatOrder>) queryWrapper).between(SbhPlatOrder::getId, prePageDto.getMinId(), prePageDto.getMaxId()); } else if (queryWrapper instanceof QueryWrapper) { ((QueryWrapper<SbhPlatOrder>) queryWrapper).lambda().between(SbhPlatOrder::getId, prePageDto.getMinId(), prePageDto.getMaxId()); } }
更好的解決辦法-Wrapper#clone
利用clone方法,mybatisplus的Wrapper的抽象父類AbstractWrapper,重寫了超類Object的clone方法,如下是原始碼:
package com.baomidou.mybatisplus.core.conditions;
public abstract class AbstractWrapper ...{ @Override @SuppressWarnings("all") public Children clone() { return SerializationUtils.clone(typedThis); } }
相比上面的解決辦法,我認為這是更好的解決辦法,這樣修正的代碼如下:
import com.baomidou.mybatisplus.core.mapper.BaseMapper; public interface SbhPlatOrderMapper extends BaseMapper<SbhPlatOrder> { @Override default IPage<SbhPlatOrder> selectPage(IPage<SbhPlatOrder> page, @Param(Constants.WRAPPER) Wrapper<SbhPlatOrder> queryWrapper){ Wrapper<SbhPlatOrder> queryWrapperClone = queryWrapper.clone(); PrePageDto prePageDto = selectCountCache(queryWrapperClone); page.setTotal(prePageDto.getRowCount()); if (prePageDto.getRowCount()>0) { if (queryWrapperClone instanceof LambdaqueryWrapperClone) { ((LambdaQueryWrapper<SbhPlatOrder>) queryWrapperClone).between(SbhPlatOrder::getId, prePageDto.getMinId(), prePageDto.getMaxId()); } else if (queryWrapperClone instanceof QueryWrapper) { ((QueryWrapper<SbhPlatOrder>) queryWrapperClone).lambda().between(SbhPlatOrder::getId, prePageDto.getMinId(), prePageDto.getMaxId()); } page.setRecords(selectPageList((page.getCurrent() - 1) * page.getSize(), page.getSize(), queryWrapperClone)); } return page; } ,,, }
EOF-thanks!
當看到一些不好的代碼時,會發現我還算優秀;當看到優秀的代碼時,也才意識到持續學習的重要!--buguge
本文來自博客園,轉載請注明原文鏈接:https://www.cnblogs.com/buguge/p/16940068.html
<style>hr.signhr{width:80%;margin:0 auto;border: 0;height: 4px;background-image: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.75), rgba(0, 0, 0, 0))}</style>
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/538822.html
標籤:其他
上一篇:Java學習十
