Mybatis Plus中的流式查询案例

目录
  • Mybatis Plus流式查询
    • 通用流式查询
  • Mybatis Plus大数据量流式查询

Mybatis Plus流式查询

mybatis plus 中自定义如下接口,就可以实现流式查询,mybatis 中同样适用。

@Select("select * from t_xxx t ${ew.customSqlSegment}")
@Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = 1000)
@ResultType(ClearReconDiffAbnormalDO.class)
void listByStream(@Param(Constants.WRAPPER) Wrapper<Model> wrapper, ResultHandler<Model> resultHandler);

通用流式查询

编写流式查询的方法:

public class FetchByStream extends AbstractMethod {
    private static final String METHOD = "fetchByStream";
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        String sqlFormat = "<script>\nSELECT %s FROM %s %s %s\n</script>";
        String sql = String.format(sqlFormat, sqlSelectColumns(tableInfo, true),
                tableInfo.getTableName(), sqlWhereEntityWrapper(true, tableInfo),
                sqlComment());
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        String statementName = mapperClass.getName() + DOT + METHOD;
        if (configuration.hasStatement(statementName, false)) {
            logger.warn(LEFT_SQ_BRACKET + statementName + "] Has been loaded by XML or SqlProvider or Mybatis's Annotation, so ignoring this injection for [" + getClass() + RIGHT_SQ_BRACKET);
            return null;
        }
        /* 缓存逻辑处理 */
        return builderAssistant.addMappedStatement(METHOD, sqlSource, StatementType.PREPARED, SqlCommandType.SELECT,
                Integer.MIN_VALUE, null, null, null, null, modelClass,
                ResultSetType.FORWARD_ONLY, true, true, false, null, null, null,
                configuration.getDatabaseId(), languageDriver, null);
    }
}

然后再注入通用方法,在Mapper 写入下方的 method 即可使用。

void fetchByStream(@Param(Constants.WRAPPER) Wrapper<T> wrapper, ResultHandler<T> handler);

Mybatis Plus大数据量流式查询

一、在需要使用流式查询的mapper文件中,定义流式查询方法

package com.unionpay.dao.db2;
 
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.unionpay.entity.TblMallOrder;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.ResultSetType;
import org.apache.ibatis.session.ResultHandler;
 
/**
 * (TblMallOrder)表数据库访问层
 *
 * @author liudong
 * @since 2020-09-15 17:07:13
 */
@Mapper
public interface TblMallOrderDao extends BaseMapper<TblMallOrder> {
    @Select("${sql}")
    @Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = 1000)
    @ResultType(TblMallOrder.class)
    void dynamicSelectLargeData1(@Param("sql") String sql, ResultHandler<TblMallOrder> handler);
 
    @Select("${sql}")
    @Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = 1000)
    @ResultType(Map.class)
    void dynamicSelectLargeData2(@Param("sql") String sql, ResultHandler<Map> handler);
}

二、使用示例

@RestController
public class TestSearchLargeData {
    // 这是每批处理的大小
    private final static int BATCH_SIZE = 1000;
    private int size;
    // 存储每批数据的临时容器
    private List<TblMallOrder> mallOrders;
 
    @Autowired
    private TblMallOrderDao tblMallOrderDao;
 
    @GetMapping("/getLargeData1")
    public void getLargeData1() {
        String sql = "select * from t_mall_order";
        tblMallOrderDao.dynamicSelectLargeData1(sql, new ResultHandler<TblMallOrder>() {
            @Override
            public void handleResult(ResultContext<? extends TblMallOrder> resultContext) {
                TblMallOrder tblMallOrder = resultContext.getResultObject();
                System.out.println(tblMallOrder);
            }
        });
    }
 
    @GetMapping("/getLargeData2")
    public void getLargeData2() {
        String sql = "select * from t_mall_order";
        tblMallOrderDao.dynamicSelectLargeData1(sql, new ResultHandler<TblMallOrder>() {
            @Override
            public void handleResult(ResultContext<? extends TblMallOrder> resultContext) {
                TblMallOrder tblMallOrder = resultContext.getResultObject();
                System.out.println(tblMallOrder);
                // 你可以看自己的项目需要分批进行处理或者单个处理,这里以分批处理为例
                mallOrders.add(tblMallOrder);
                size++;
                if (size == BATCH_SIZE) {
                    handle();
                }
            }
        });
        //用来完成最后一批数据处理
        handle();
    }
    /**
     * 数据处理
     */
    private void handle(){
        try{
            // 在这里可以对你获取到的批量结果数据进行需要的业务处理
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            // 处理完每批数据后后将临时清空
            size = 0;
            mallOrders.clear();
        }
    }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 扩展tk.mybatis的流式查询功能实现

    mybatis查询默认是一次获取全部, 有时候需要查询上万上百万数据时,如果一次性读取到内存中,会容易导致OOM问题.这时候需要采用流式查询.以下扩展了tk.mybatis的流式查询功能. 直接上干货: @Options注解是关键 import org.apache.ibatis.annotations.Options; import org.apache.ibatis.annotations.SelectProvider; import org.apache.ibatis.mapping.Re

  • MyBatis流式查询的三种实现方法

    导读:流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果.流式查询的好处是能够降低内存使用 如果没有流式查询,我们想要从数据库取 1000 万条记录而又没有足够的内存时,就不得不分页查询,而分页查询效率取决于表设计,如果设计的不好,就无法执行高效的分页查询.因此流式查询是一个数据库访问框架必须具备的功能. 流式查询的过程当中,数据库连接是保持打开状态的,因此要注意的是:执行一个流式查询后,数据库访问框架就不负责关闭数据库连接了,需要应用在取完数据后自己关闭

  • MyBatis如何实现流式查询的示例代码

    基本概念 流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果.流式查询的好处是能够降低内存使用. 如果没有流式查询,我们想要从数据库取 1000 万条记录而又没有足够的内存时,就不得不分页查询,而分页查询效率取决于表设计,如果设计的不好,就无法执行高效的分页查询.因此流式查询是一个数据库访问框架必须具备的功能. 流式查询的过程当中,数据库连接是保持打开状态的,因此要注意的是:执行一个流式查询后,数据库访问框架就不负责关闭数据库连接了,需要应用在取完数据后自

  • Mybatis Plus中的流式查询案例

    目录 Mybatis Plus流式查询 通用流式查询 Mybatis Plus大数据量流式查询 Mybatis Plus流式查询 mybatis plus 中自定义如下接口,就可以实现流式查询,mybatis 中同样适用. @Select("select * from t_xxx t ${ew.customSqlSegment}") @Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = 1000) @Resul

  • MySQL中使用流式查询避免数据OOM

    一.前言 程序访问MySQL数据库时,当查询出来的数据量特别大时,数据库驱动把加载到的数据全部加载到内存里,就有可能会导致内存溢出(OOM). 其实在MySQL数据库中提供了流式查询,允许把符合条件的数据分批一部分一部分地加载到内存中,可以有效避免OOM:本文主要介绍如何使用流式查询并对比普通查询进行性能测试. 二.JDBC实现流式查询 使用JDBC的PreparedStatement/Statement的setFetchSize方法设置为Integer.MIN_VALUE或者使用方法State

  • MySQL中的流式查询及游标查询方式

    目录 一.业务场景 二.罗列一下三种处理方式 2.1 常规查询 2.2 流式查询 2.3 游标查询 三.RowData 3.1 RowDataStatic 3.2 RowDataDynamic 3.3 RowDataCursor 四.JDBC 通信原理 4.1 generalQuery 普通查询 4.2 streamQuery 流式查询 4.3 cursorQuery 游标查询 五.并发场景 六.总结 一.业务场景 现在业务系统需要从 MySQL 数据库里读取 500w 数据行进行处理 迁移数据

  • jdbc和mybatis的流式查询使用方法

    目录 导语: jdbc流式查询: mybatis流式查询: 导语: 有些时候我们所需要查询的数据量比较大,但是jvm内存又是有限制的,数据量过大会导致内存溢出.这个时候就可以使用流式查询,数据一条条的返回,处理完一条在拿下一条数据,这样每次在内存里面的数据其实很小,不会导致内存溢出. 本文里面会讲到jdbc的流式查询和mybatis的流式查询. jdbc流式查询: jdbc的流式查询需要在生成PreparedStatement的时候设置三个参数.如下: PreparedStatement stm

  • MyBatis流式查询的使用详解

    目录 1.应用场景说明 2.模拟excel导出场景 1.创建海量数据的sql脚本 2.MyBatis流式查询 3.Excel通用导出工具类 1.Excel导入导出工具类 2.Excel数据读取监听器 3.Excel读取数据完成回调接口 4.拆分List集合工具类 4.测试结果 5.遗留问题待处理 1.应用场景说明 MyBatis preview: JDBC三种读取方式: 1.一次全部(默认):一次获取全部. 2.流式:多次获取,一次一行. 3.游标:多次获取,一次多行. 在开发中我们经常需要会遇

  • MyBatis流式查询的项目实践

    目录 1.应用场景说明 MyBatis 2.模拟excel导出场景 1.创建海量数据的sql脚本 2.MyBatis流式查询 3.Excel通用导出工具类 4.测试结果 5.遗留问题,待处理 1.应用场景说明 MyBatis preview: JDBC三种读取方式:1.一次全部(默认):一次获取全部.2.流式:多次获取,一次一行.3.游标:多次获取,一次多行. 在开发中我们经常需要会遇到统计数据,将数据导出到excel表格中.由于生成报表逻辑要从数据库读取大量数据并在内存中加工处理后再生成Exc

  • 详解mybatis流式查询与分页插件

    目录 1.流式查询 1.实体类 2.mapper 3.mapper配置 4.自定义处理结果集 5.service层 2.分页插件 1.引入依赖 2.配置文件 3.mapper接口 4.mapper配置 5.servlce层 1.流式查询 1.实体类 package com.wanqi.pojo; import java.util.Date; /** * @Description TODO * @Version 1.0.0 * @Date 2022/9/12 * @Author wandaren

随机推荐