MyBatis Plus 从 3.5.4 版本开始正式支持流式查询,其底层基于 MyBatis 原生的 ResultHandler 接口实现,属于 MyBatis 原生能力增强。
流式查询不会将结果集一次性加载到 JVM 内存,而是逐条从数据库读取并处理,专门用于大数据量跑批、数据同步、报表导出、全表处理等易引发内存溢出(OOM)的业务场景。
避免内存溢出:不一次性加载全部数据,逐条处理,内存占用极低
原生支持:基于 MyBatis 底层实现,无额外依赖,性能稳定
无缝兼容:可直接使用 MP 条件构造器、分页、逻辑删除等原有能力
可控性强:支持中途停止查询、计数统计、自定义单条处理逻辑
MyBatis Plus 版本 ≥ 3.5.4
Mapper 接口继承 BaseMapper<T>
数据库支持流式结果集(MySQL、Oracle、PostgreSQL 均支持)
MP 在 BaseMapper 中新增了支持 ResultHandler 的重载方法,可直接传入处理器实现流式处理:
selectList(Wrapper<T> queryWrapper, ResultHandler<T> resultHandler)
selectList(Page<T> page, Wrapper<T> queryWrapper, ResultHandler<T> resultHandler)
selectByMap(Map<String, Object> map, ResultHandler<T> resultHandler)
selectBatchIds(Collection<? extends Serializable> idList, ResultHandler<T> resultHandler)
selectMaps(Wrapper<T> queryWrapper, ResultHandler<Map<String, Object>> resultHandler)
selectObjs(Wrapper<T> queryWrapper, ResultHandler<Object> resultHandler)
结果处理器,用于定义每一条数据的处理逻辑,只需重写 handleResult 方法。
结果上下文对象,提供流式查询的核心操作方法:
分页 + 流式查询(大数据跑批推荐)
适用于百万级数据分批处理,避免一次性加载全量数据导致 OOM。
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.Page;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.apache.ibatis.session.ResultContext;
import org.apache.ibatis.session.ResultHandler;
// 分页参数:第 1 页,每页 100000 条
Page<H2User> page = new Page<>(1, 100000);
// 关闭 count 查询,大数据量下提升性能
page.setSearchCount(false);
baseMapper.selectList(page, Wrappers.lambdaQuery(), new ResultHandler<H2User>() {
@Override
public void handleResult(ResultContext<? extends H2User> resultContext) {
// 1. 获取当前单条数据
H2User user = resultContext.getResultObject();
// 2. 获取当前处理条数
long currentNum = resultContext.getResultCount();
// 3. 执行业务处理(数据转换、同步、导出等)
System.out.println("流式处理第 " + currentNum + " 条数据:" + user);
// 4. 满足条件可手动停止流式查询
if (currentNum >= 50000) {
resultContext.stop();
}
}
});全表流式查询(无分页)
适用于全表数据扫描、数据初始化、数据校验等场景。
baseMapper.selectList(Wrappers.lambdaQuery(H2User.class).eq(H2User::getStatus, 1),
new ResultHandler<H2User>() {
@Override
public void handleResult(ResultContext<? extends H2User> resultContext) {
H2User user = resultContext.getResultObject();
// 业务处理逻辑
doBusiness(user);
}
});Map 类型流式查询
无需实体类,直接处理 Map 结构数据。
baseMapper.selectMaps(Wrappers.lambdaQuery(H2User.class),
new ResultHandler<Map<String, Object>>() {
@Override
public void handleResult(ResultContext<? extends Map<String, Object>> resultContext) {
Map<String, Object> map = resultContext.getResultObject();
System.out.println(map);
}
});大数据量处理:优先使用分页 + 流式查询,每页数据量控制在 1000~100000 条
禁止全表更新:流式查询仅用于读取数据,不建议在处理中执行更新 / 删除操作
分批提交:若需批量写入,可每处理 1000 条 集中执行一次批量操作
异常处理:在 handleResult 中捕获异常,避免单条数据异常导致整个流式任务中断
MyBatis Plus 流式查询是大数据量处理的最优方案:
底层基于 MyBatis 原生 ResultHandler,3.5.4+ 版本支持
逐条加载数据,彻底避免 OOM
兼容条件构造器、分页、逻辑删除等 MP 核心能力
支持手动计数、中途停止,可控性极强
适用于数据跑批、全表处理、数据同步、报表导出等场景