MyBaties自定义Handler流式读取数据库

一、前言

     最近有个需求,需要从一个很大的表中读取数据,每次读取的数据量最大估计为100W条,计算后大概是120M的样子。此表虽然做了分区,但是一次读取100W数据可能会卡住,长时间读不出来。因此采用流式读取的方式,一条一条读取出来。经过实际测试,发现获取100W数据耗时减少了很多。

二、使用方法

     第一种办法是借助匿名内部类实现,网上大多介绍是匿名内部类的实现方法,本文不再重复。下面介绍一下我日常用的一种实现方法

     建立一个抽象类QueryRecordHandler,里面的execute就是具体每个handler要实现的内容

import org.apache.ibatis.session.ResultContext;
import org.apache.ibatis.session.ResultHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

public abstract class QueryRecordHandler implements ResultHandler {
    public final Logger logger = LoggerFactory.getLogger(QueryRecordHandler.class);

    protected Map value = new HashMap<>();
    Map row;

    protected abstract void execute(Map row);

    @Override
    public void handleResult(ResultContext context) {
        row = (Map) context.getResultObject();
        execute(row);
    }
    public Map getValue(){
        return this.value;
    }
}

     然后建立针对某个具体业务实现的handler,塞上你的具体实现。如果你需要传进来某些参数,可以像bean一样,直接声明,并提供set方法,然后在调用的时候,置入值即可。

@Slf4j
public class TransRecordHandler extends QueryRecordHandler {

    @Override
    protected void execute(Map row) {
        Long id = Long.valueOf(row.get("ID").toString());
        String bizType = (String) row.get("BIZTYPE");
        value.put(id, bizType);
    }
}

     怎么调用呢?如下:

TransRecordHandler handler = new TransRecordHandler();
handler.setMap(map);
transactionRecordEntityMapper.selectNoFailRecord(参数1, 参数2, 参数3, handler);
return handler.getValue();

    还是你原来的查询方法,只是参数新增了一个handler,引入语句import org.apache.ibatis.session.ResultHandler;意思就是查询出来的内容由你自定义的handler处理。

三、注意事项

     这里的流式读取只是个抽象概念,实际是保有一个长连接,然后一条一条读取。l另外注意dao层方法不能再有返回值,而是通过handler.getValue()获取。

 

你可能感兴趣的:(LM日常)