有時候,數據庫中的內容太多,無法一次查詢出來,這時候就需要分批查詢。如果在每個需要分批查詢的地方,都去修改原來的代碼,實現分批,這樣會很麻煩。而Mybatis的分頁插件,正好可以配合AOP來進行無侵入式分頁,不需要修改原有的代碼。下面介紹一下實現步驟:
環境:springBoot+mybatis
1.在工程中引入mybatis的分頁插件
compile("com.baomidou:mybatis-plus-boot-starter:2.3")
compile group: 'com.github.pagehelper', name: 'pagehelper', version: '5.1.11'
2.把分頁插件傳入SqlSessionFactoryBean
@Configuration
@MapperScan("demo.dao")
public class MybatisConfig {
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource)
throws Exception{
SqlSessionFactoryBean fb = new SqlSessionFactoryBean();
fb.setDataSource(dataSource);
fb.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources("classpath:demo/dao/*.xml"));
Interceptor[] plugins = new Interceptor[1];
plugins[0] = paginationInterceptor();
fb.setPlugins(plugins);
return fb.getObject();
}
/**
* mybatis分頁插件,因爲我使用oracle數據庫,所以這裏傳入了oracle
* @return
*/
public Interceptor paginationInterceptor() {
PageInterceptor pageInterceptor = new PageInterceptor();
Properties properties = new Properties();
properties.setProperty("helperDialect","Oracle");
pageInterceptor.setProperties(properties);
return pageInterceptor;
}
}
3.自定義一個註解@PageDao,這裏有3個變量,value代表分頁操作的名稱,size表示分頁大小,returnValue表示是否需要一次返回所有批次的值
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PageDao {
/**
* 分批操作名稱
*/
String value() default "";
/**
* 分頁大小,默認100
*/
int size() default 100;
/**
* 分批查詢方法是否需要返回值,默認不返回
* 如果需要返回所有批次的值,可能分批就沒有意義,分批是爲了解決內存溢出的問題
*/
boolean returnValue() default false;
}
4.定義一個切面,使用@PageDao作爲切面
@Aspect
@Component
public class PageDaoAop {
@Around("@annotation(pageDao)")
public Object around(ProceedingJoinPoint joinPoint, PageDao pageDao) throws Throwable{
int page = 1;
int size = pageDao.size();
if(size<=0)
size = 100;
boolean returnValue = pageDao.returnValue();
List<Object> totalResult = new ArrayList<>();
while(true){
Page pageInfo = PageHelper.startPage(page, size);
Object result = joinPoint.proceed();
System.out.println(pageDao.value()
+" 當前頁數["+page
+"],頁大小["+pageInfo.getPageSize()
+"],當頁大小["+(pageInfo.getResult().size())
+"],總頁數["+pageInfo.getPages()
+"],總記錄數["+pageInfo.getTotal()+"]"
);
if(returnValue) {
if (result instanceof Collection) {
Collection<?> collection = (Collection<?>) result;
totalResult.addAll(collection);
} else {
totalResult.add(result);
}
}
if(pageInfo.getPageNum()>=pageInfo.getPages()){
break;
}
page++;
pageInfo.setCount(false);
}
if(returnValue)
return totalResult;
return null;
}
}
5.使用。我們在service的方法上註解上@PageDao,其餘代碼不需要變
@PageDao(value = "網元參數遷移", size = 10000)
public void doTask() {
List<String> results = mapper.selectAll(); //直接調用mybatis的mapper的列表全查方法即可
//查詢結果以追加方式寫入文件,所以不需要一次返回所有批次的結果
//FileUtils是自己寫的類
FileUtils.writeFile(results ,"dist\\test.sql", true);
}
6.效果
網元參數遷移 當前頁數[1],頁大小[10000],當頁大小[10000],總頁數[105],總記錄數[1040376]
網元參數遷移 當前頁數[2],頁大小[10000],當頁大小[10000],總頁數[105],總記錄數[1040376]
網元參數遷移 當前頁數[3],頁大小[10000],當頁大小[10000],總頁數[105],總記錄數[1040376]
網元參數遷移 當前頁數[4],頁大小[10000],當頁大小[10000],總頁數[105],總記錄數[1040376]
網元參數遷移 當前頁數[5],頁大小[10000],當頁大小[10000],總頁數[105],總記錄數[1040376]
網元參數遷移 當前頁數[6],頁大小[10000],當頁大小[10000],總頁數[105],總記錄數[1040376]
網元參數遷移 當前頁數[7],頁大小[10000],當頁大小[10000],總頁數[105],總記錄數[1040376]
網元參數遷移 當前頁數[8],頁大小[10000],當頁大小[10000],總頁數[105],總記錄數[1040376]
網元參數遷移 當前頁數[9],頁大小[10000],當頁大小[10000],總頁數[105],總記錄數[1040376]
網元參數遷移 當前頁數[10],頁大小[10000],當頁大小[10000],總頁數[105],總記錄數[1040376]
...
網元參數遷移 當前頁數[100],頁大小[10000],當頁大小[10000],總頁數[105],總記錄數[1040376]
網元參數遷移 當前頁數[101],頁大小[10000],當頁大小[10000],總頁數[105],總記錄數[1040376]
網元參數遷移 當前頁數[102],頁大小[10000],當頁大小[10000],總頁數[105],總記錄數[1040376]
網元參數遷移 當前頁數[103],頁大小[10000],當頁大小[10000],總頁數[105],總記錄數[1040376]
網元參數遷移 當前頁數[104],頁大小[10000],當頁大小[10000],總頁數[105],總記錄數[1040376]
網元參數遷移 當前頁數[105],頁大小[10000],當頁大小[376],總頁數[105],總記錄數[1040376]