函數式接口
獲取分頁數據接口
主要用于獲取數據
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;@FunctionalInterface
public interface MyBatisPlusPageFunctionInterface<T> {Page<T> selectPage(Page<T> page);}
數據處理接口
import java.util.List;@FunctionalInterface
public interface MyBatisPlusFunctionInterface<T> {void execute(List<T> tList);}
通用邏輯工具類
用于執行分頁數據接口實現和數據處理接口實現邏輯
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;import java.util.List;/*** MyBatis-Plus 工具類*/
public final class MyBatisPlusUtils {public static final int DEFAULT_PAGE_SIZE_INT = 1000;public static final long DEFAULT_PAGE_SIZE = 1000L;private MyBatisPlusUtils() {}/*** 無條件分頁查詢N條(N由調用方決定)** @param extendsBaseMapperClass 繼承了BaseMapper的Mapper接口* @param myBatisPlusFunctionInterface 業務邏輯*/public static <T> void findByPage(BaseMapper<T> extendsBaseMapperClass, long pageSize, MyBatisPlusFunctionInterface<T> myBatisPlusFunctionInterface) {findByPage(extendsBaseMapperClass, null, pageSize, myBatisPlusFunctionInterface);}/*** 無條件分頁查詢(默認每次取1000條,直到取完為止)** @param extendsBaseMapperClass 繼承了BaseMapper的Mapper接口* @param myBatisPlusFunctionInterface 業務邏輯*/public static <T> void findByPage(BaseMapper<T> extendsBaseMapperClass, MyBatisPlusFunctionInterface<T> myBatisPlusFunctionInterface) {findByPage(extendsBaseMapperClass, null, DEFAULT_PAGE_SIZE, myBatisPlusFunctionInterface);}/*** 有條件分頁查詢(默認每次取1000條,直到取完為止)** @param extendsBaseMapperClass 繼承了BaseMapper的Mapper接口* @param myBatisPlusFunctionInterface 業務邏輯*/public static <T> void findByPage(BaseMapper<T> extendsBaseMapperClass, LambdaQueryWrapper<T> lambdaQueryWrapper, MyBatisPlusFunctionInterface<T> myBatisPlusFunctionInterface) {findByPage(extendsBaseMapperClass, lambdaQueryWrapper, DEFAULT_PAGE_SIZE, myBatisPlusFunctionInterface);}/*** 后端分頁查詢所有數據** @param extendsBaseMapperClass 繼承了BaseMapper的Mapper接口* @param myBatisPlusFunctionInterface 業務邏輯*/public static <T> void findByPage(BaseMapper<T> extendsBaseMapperClass, LambdaQueryWrapper<T> lambdaQueryWrapper, long pageSize, MyBatisPlusFunctionInterface<T> myBatisPlusFunctionInterface) {findByPage((Page<T> page) -> extendsBaseMapperClass.selectPage(page, lambdaQueryWrapper), pageSize, myBatisPlusFunctionInterface);}/*** 通用分頁查詢方法** @param functionInterface 獲取分頁數據的方法* @param pageSize 每次獲取的數據量* @param myBatisPlusFunctionInterface 對獲取的分頁數據進行處理*/public static <T> void findByPage(MyBatisPlusPageFunctionInterface<T> functionInterface, long pageSize, MyBatisPlusFunctionInterface<T> myBatisPlusFunctionInterface) {// 參數校驗Assert.isTrue(pageSize > 0, "每頁大小必須大于 0");Assert.notNull(myBatisPlusFunctionInterface, "數據處理邏輯不能為 null");int currentPage = 1;while (true) {Page<T> tPage = functionInterface.selectPage(Page.of(currentPage, pageSize));long pages = tPage.getPages();List<T> records = tPage.getRecords();//數據為空if (CollectionUtils.isEmpty(records)) {return;}// 業務邏輯myBatisPlusFunctionInterface.execute(records);//最后一頁if (pages <= currentPage) {return;}currentPage++;}}}
使用方法
簡單查詢
//批量獲取全部數據,沒設置一次取幾條數據,這里默認取1000條。MyBatisPlusUtils.findByPage(XXXMapper,//簡單查詢繼承了BaseMapper的Mappernew LambdaQueryWrapper<DataBaseEntity>().isNull(DataBaseEntity::getName),//簡單查詢mapper的條件records -> {//處理分頁查詢出來的數據,如果有多次分頁,則進行多次處理。比如有2頁,則下面的方法會執行2次。List<DataBaseEntity> l = new ArrayList<>(MyBatisPlusUtils.DEFAULT_PAGE_SIZE_INT);//遍歷處理這一批次的數據for (DataBaseEntity record : records) {//處理查詢到的數據}}});
自定義查詢方法
//自定義查詢方法MyBatisPlusUtils.findByPage((Page<HiBdSrvtmpMedOrd> page) -> {//對傳入的數據進行處理String param2 = dto.getParam2() + dto.getParam3();return hiBdSrvtmpMedOrdMapper.findPage(page, param2);//使用自定義的分頁方法,并且分頁參數可以不固定,需要多少個都行。},//使用自定義的分頁方法2000L,//一次取2000條數據records -> {//遍歷處理這一批次的數據for (HiBdSrvtmpMedOrd record : records) {//處理查詢到的數據}});
總結
上面提供的方式對于初學者或者沒有系統了解過JAVA8的函數式接口、lambda表達式、匿名函數等新特性的人,理解起來是非常抽象、不好理解的,但是正因為代碼抽象,所以功能才更強大!
還有其它組合使用方式沒有一一列舉出來,大家可以自行嘗試使用和擴展。
有些功能沒有考慮在內,比如:分批提交的事務問題、沒有使用批處理模式(ExecutorType.BATCH)、使用 Cursor進行流式查詢(適用于大數據量)、多線程處理(代碼會更復雜,而且我也沒有想過通用這方面的代碼,這方面單獨的代碼會更合適)
有更好的辦法,歡迎留言,謝謝。