程序员的知识教程库

网站首页 > 教程分享 正文

MyBatis-三种流式查询方法千万条数据不用分页

henian88 2024-08-15 22:02:54 教程分享 14 ℃ 0 评论

流式查询指的是:查询结束后不是返回一个汇合而是返回一个迭代器,利用每次从迭代器取一条查问后果。如果没有流式查询,想要从数据库取 1000 万条记录而又没有足够的内存时,就不得不分页查询。

MyBatis 流式查询接口Cursor提供了三个方法:

  • isOpen():用于在取数据之前判断 Cursor 对象是否是关闭。
  • isConsumed():用于判断查询结果是否全部取完。
  • getCurrentIndex():返回已经获取了多少条数据。

因为 Cursor 实现了迭代器接口,因而在理论应用当中,从 Cursor 取数据非常简单:

cursor.forEach(rowObject -> {…})。

例子:

1、Dao:如下图在mapper里有一个返回结果用Cursor封装的queryPage方法

@Mapper
public interface TmMaterialLackRecordDao extends BaseMapper<TmMaterialLackRecord> {
      
    Cursor<TmMaterialLackRecordVo> queryPage(@Param("pageBo") TmMaterialLackRecordPageBo pageBo);
}

2、Dao.xml:TmMaterialLackRecordDao对应的xml文件里定义具体的查询sql

<?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="com.asm.abc.dao.TmMaterialLackRecordDao">
    <select id="queryPage" resultType="com.asm.abc.vo.TmMaterialLackRecordVo">
        select p.saas_id,p.plant_id from t_tm_material_lack_record p
        where p.is_del !=1
        <if test="pageBo.saasId !=null and pageBo.saasId!=''">
            and p.saas_id = #{pageBo.saasId}
        </if>
        <if test="pageBo.plantId !=null and pageBo.plantId != 0 ">
            and p.plant_id = #{pageBo.plantId}
        </if>
        order by p.check_date_time desc
    </select>
</mapper>

3、service层调用Dao层查询,@SneakyThrows注解是抛出异常的意思,lombok的注解

@SneakyThrows
@Transactional
public void exportMaterialLackRecord(TmMaterialLackRecordPageBo pageBo) {
    
    List<TmMaterialLackRecordVo> list = new ArrayList<>();
    try (Cursor<TmMaterialLackRecordVo> export = this.baseMapper.queryPage(pageBo)) {
        export.forEach(foo -> list.add(foo));
    }
}

注意:@Transactional是为了保证数据库长连接,不然会抛出java.lang.IllegalStateException: A Cursor is already closed。另外还有两种实现方式TransactionTemplate和SqlSessionFactory可以自行验证。@Transactional 注解标注的方法只能被不同的类来调用,在当前类里的其他方法调用该注解标注的方法会导致事务失效。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表