JDBC从数据库获取数据的三种读取方式:
1.一次全部(默认):一次获取全部。
2.流式:多次获取,一次一行。
3.游标:多次获取,一次多行。
mybatis没有任何配置的话是采取第一种方式 当数据量比较大的时候 容易引发oom
现在介绍第二种:流式获取数据
代码示例
mapper 层:

/**
* @author zhanglf
*/
@Mapper
public interface OdsWwPersReceiptAcctDtMapper{
void getExportInfosByDateByHandler(@Param("financialContractUuids") List<String>financialContractUuids, @Param("startTime") Date startTime, @Param("endTime") Date endTime, OdsExportResultHandler resultHandler);
}
对应mapper.xml为
框中的fetchSize需要为-2147483648 流式获取才会生效
<select id="getExportInfosByDateByHandler" parameterType="map" resultType="com.suidifu.ods.export.model.OdsWwPersReceiptAcctDtModel" fetchSize="-2147483648">
select *
from ods_ww_pers_receipt_acct_dt
where
data_status=0
and create_time >= #{startTime}
and create_time < #{endTime}
<if test="null!=financialContractUuids and financialContractUuids.size()>0">
and
financial_contract_uuid in
<foreach item="item" index="index" collection="financialContractUuids" open="(" separator="," close=")">
#{item}
</foreach>
</if>
</select>
还需要继承ResultHandler 实现类为
红框中可以添加单条处理逻辑
/**
* @param <T,K>
* @author zhanglf
*/
@AllArgsConstructor
@NoArgsConstructor
@Log4j2
public class OdsExportResultHandler<T extends OdsCommModel> implements ResultHandler<T> {
private int total=0;
/**
* 每批处理的大小
*/
private int batchSize = 100;
private int size;
private OdsDataType type;
private String odsLocalPath;
private boolean existData = false;
private OutputStreamWriter writer;
private BufferedReader reader;
/**
* 存储每批数据的临时容器
*/
private List<T> ods = new ArrayList<>();
public OdsExportResultHandler(int size, OdsDataType type,String odsLocalPath,OutputStreamWriter writer,BufferedReader reader) {
this.batchSize = size;
this.type = type;
this.odsLocalPath = odsLocalPath;
this.writer =writer;
this.reader=reader;
}
@Override
public void handleResult(ResultContext resultContext) {
T od = (T) resultContext.getResultObject();
existData = true;
ods.add(od);
size++;
if (size == batchSize) {
handle();
}
}
private void handle() {
try {
log.info("OdsExportResultHandler deal type[{}] size[{}], start.",type.getName(),ods.size());
dealDataToLocal(ods, type,odsLocalPath,writer,reader);
log.info("OdsExportResultHandler deal type[{}] size[{}], end. 目前共处理[{}]条",type.getName(),ods.size(),total+ods.size());
} catch (Exception e) {
e.printStackTrace();
log.error("导出失败");
} finally {
size = 0;
ods.clear();
}
}
public void end() {
if (CollectionUtils.isEmpty(ods) && existData) {
return;
}
handle();
}
public void closeBuffer(){
try {
writer.close();
reader.close();
}catch(Exception e){
log.error("文件关闭失败 reason is [{}]",ExceptionUtils.getStackTrace(e));
}
}
}
本文介绍使用MyBatis流式读取大数据的方法,通过配置fetchSize和实现ResultHandler接口,有效避免了大数据量读取时的内存溢出问题。文章详细展示了如何在Mapper接口和XML中设置参数,并提供了完整的代码示例。

被折叠的 条评论
为什么被折叠?



