4人参与 • 2026-09-21 • Java
mybatis 的默认查询行为是“全量加载”:jdbc 驱动把整个 resultset 缓存到客户端内存,mybatis 再逐行映射成 java 对象塞进 list。数据量少的时候没有问题,但是数据量一旦多起来,这就是一颗内存炸弹
其中一个解决办法就是 mybatis 的 resulthandler 流式查询。它让结果集不再一次性加载,而是每读取一条数据就回调一次 handleresult 方法,处理完立即释放
本文包含完整的测试代码:xml 配置、mapper 接口定义、service 回调实现、测试类调用。拿来就能跑,跑通就能用。
<?xml version="1.0" encoding="utf-8" ?>
<!doctype mapper public "-//mybatis.org//dtd mapper 3.0//en" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="wxw.mengyuan.dsf.entity.operations.systemmonitor.thread.mapper.threadmapper">
<!-- 流式查询 --> <!-- fetchsize:设置为 integer 的最小值,代表开启流式查询 -->
<select id="streamquery" resulttype="wxw.mengyuan.dsf.entity.operations.systemmonitor.thread.entity.threadentity" fetchsize="-2147483648">
select * from dsf_thread where collect_time between #{start} and #{end} order by collect_time desc, id desc
</select>
</mapper>/** * 线程信息数据类 */
@mapper
@repository
public interface threadmapper extends basemapper<threadentity> {
/**
* 流式读取
* @param start 开始时间
* @param end 结束时间
* @param handler 结果集处理器
*/
// 注意事项
// (1) 返回结果必须为 void
// (2) 在传入参数之后,必须使用 resulthandler 对象接收返回结果
void streamquery(@nonnull @param("start") localdatetime start, @nonnull @param("end") localdatetime end, resulthandler<sqllogentity> handler);
}
/**
* 线程信息业务类
*/
@slf4j
@service
public class threadservice extends serviceimpl<threadmapper, threadentity> {
/**
* 流式读取
* @param start 开始时间
* @param end 结束时间
*/
public void streamquery(@nonnull localdatetime start, @nonnull localdatetime end) {
long starttime = system.currenttimemillis();
atomicinteger count = new atomicinteger(0);
this.basemapper.streamquery(start, end, new resulthandler<sqllogentity>() {
@override
public void handleresult(resultcontext<? extends sqllogentity> resultcontext) {
// 打印日志 log.warn("当前已经遍历了 {} 条数据", count.incrementandget());
// 获取一条数据:包装好的实体类对象
// system.out.println(resultcontext.getresultobject());
// 满足某种条件时,停止数据获取(关闭resultset,后续不会再进入当前回调函数)
if (count.get() >= 1000000) {
resultcontext.stop();
}
}
});
log.warn("耗时 {} 毫秒", system.currenttimemillis() - starttime);
}
}
/**
* mybatis案例
*/
@springboottest(classes = operationsapplication.class)
public class mybatisdemo {
/** 线程信息业务类 */
@autowired
private threadservice threadservice;
@test
public void mybatistest() {
threadservice.streamquery(localdatetime.now().minusyears(1), localdatetime.now());
}
}
测试结果示例

到此这篇关于mybatis流式查询之resulthandler处理海量数据的完整教学的文章就介绍到这了,更多相关mybatis resulthandler流式查询内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论