有时候,数据库中的内容太多,无法一次查询出来,这时候就需要分批查询。如果在每个需要分批查询的地方,都去修改原来的代码,实现分批,这样会很麻烦。而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]