mybatis 流式读取大量MySQL数据

 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 &gt;= #{startTime}
    and create_time &lt; #{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));
        }
    }
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis Plus是基于MyBatis的一个增强工具,通过提供更简洁、更方便的API,简化了对数据库的操作。相比于原生的MyBatisMyBatis Plus提供了更丰富的功能和更高效的性能。而Oracle和MySQL都是常见的关系型数据库,它们在底层实现原理和语法特性上有一些不同。 对于双数据源的配置,可以通过MyBatis Plus的多数据源配置来实现。首先,需要在配置文件中定义两个不同的数据源,分别对应Oracle和MySQL。可以使用不同的dataSource和transactionManager配置来指定每个数据源的连接和事务管理。 然后,在代码中使用@DS注解来指定具体是使用哪个数据源。@DS注解可以标记在类级别和方法级别,用来指定使用的数据源。例如,@DS("oracle")标记在类级别上,表示该类中的所有方法都使用Oracle数据源,而@DS("mysql")标记在方法级别上,表示该方法使用MySQL数据源。 通过这样的配置,就可以实现在同一个应用中同时使用Oracle和MySQL数据源。在使用的过程中,可以根据业务需求灵活选择具体使用的数据库。同时,MyBatis Plus还提供了很多便捷的方法和功能,可以更方便地进行数据库操作。 总之,通过MyBatis Plus的多数据源配置,可以很方便地实现Oracle和MySQL数据源的使用。这样的配置对于一些需要同时操作多个数据库的应用来说非常有用,可以满足不同业务需求的多样性。使用MyBatis Plus可以提高开发效率和代码质量,使数据库操作变得更简单和高效。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值