首页 > 其他分享 >myBatis 流式查询,大数据量查询

myBatis 流式查询,大数据量查询

时间:2023-07-20 14:46:33浏览次数:39  
标签:mapper domainList 游标 查询 数据量 myBatis import

myBatis-plus/myBatis 流式查询,大数据量查询

myBatis这个开源框架的好处就不再赘述, myBatis-plus则更是myBatis的增强工具,框架给我提供很多查询数据方式,非常方便, 这里就介绍一下流式查询,也就是游标的方式去查询。

我们在完成工作的途中会遇到大数据量的查询,比如大量数据的导出等等,我们直接用list() 方法去查询的话, 会很慢很卡,因为框架耗费大量的时间和内存去把数据库查询的大量数据封装成我们想要的实体类,在这个过程中很可能使我们的项目报内存溢出 OOM(out of memory) 的异常,所以这个时候我们需要用框架的原生数据查询了,如下:

把整理类都给出来,方便在查找问题,屏蔽了部分本地路径

  1. mapper
package com.***.mapper;

import com.***.OrgData;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.ResultSetType;
import org.apache.ibatis.session.ResultHandler;

/**

 * @Author sugar
 */
@Mapper
public interface OrgDataMapper extends BaseMapper<OrgData> {


    @Select("select * from org_data t ${ew.customSqlSegment}")
    @Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = 1000)
    @ResultType(OrgData.class)
    void getOrgWithBigData(@Param(Constants.WRAPPER) QueryWrapper<OrgData> wrapper, ResultHandler<OrgData> handler);



}

123456789101112131415161718192021222324252627

注释:

@Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = 1000)
1
  • ResultSetType.FORWARD_ONLY 表示游标只向前滚动
  • fetchSize 每次获取量
 @ResultType(OrgData.class)
1
  1. 转换成返回实体类型

注意: 返回类型必须为void 哦,因为在handler里处理数据,所以这个hander 也是必须的

  1. mapper调用使用

        orgDataMapper.getOrgWithBigData(queryWrapper,resultContext -> {

            OrgData orgData = resultContext.getResultObject();
           //这边循环调用就可以实现业务了
}
123456

end

背景

对大量数据进行处理时,为防止内存泄漏情况发生,所以采用mybatis plus游标方式进行数据查询处理,当查询百万级的数据的时候,使用游标可以节省内存的消耗,不需要一次性取出所有数据,可以进行逐条处理或逐条取出部分批量处理

mapper层

  1. 使用Cursor类型进行数据接收
  2. @Options,fetchSize设置为Integer最小值
  3. @Select,写查询sql
@Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = Integer.MIN_VALUE)
@Select("select domain from illegal_domain where icpstatus != #{icpstatus}")
Cursor<IllegalDomain> getDayJobDomain(@Param("icpstatus") Integer icpstatus);
123

service层

Cursor<IllegalDomain> domainList = illegalDomainMapper.getDayJobDomain(1);
1

数据处理

  1. forEach方式
domainList.forEach(illegalDomain -> {
    //处理逻辑,根据业务需求自行完成
    Future<IcpStatusVo> future = checkIcpThreadPool.submit(new IcpCheckThread(illegalDomain.getDomain(), configMap));
    results.add(future);
});
12345
  1. 迭代器
Iterator<IllegalDomain> iter = domainList.iterator();

while (iter.hasNext()) {

    <!--// Fetch next 10 employees-->
    <!--for(int i = 0; i<10 && iter.hasNext(); i++) {-->
    <!--    smallChunk.add(iter.next());-->
    <!--}-->
    
    //处理逻辑,根据业务需求自行完成
    Future<IcpStatusVo> future = checkIcpThreadPool.submit(new IcpCheckThread(illegalDomain.getDomain(), configMap));
    results.add(future);
}
12345678910111213

资源释放

使用完毕后,在finally块释放资源,否则游标不关闭也可能会导致内存溢出问题

try{
    //your code
    
} catch (Exception e) {
    log.error(e);
} finally {
    if(null != domainList){
        try {
            domainList.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
1234567891011121314

标签:mapper,domainList,游标,查询,数据量,myBatis,import
From: https://www.cnblogs.com/xiondun/p/17568365.html

相关文章

  • mysql查询数据库重复数据
    查询重复领取的优惠券//查询8888888用户优惠券状态为未使用且数量大于2的用户领取过的优惠券SELECTdiscount_coupon_id,count(discount_coupon_id)ascFROM`faith_user_discount_coupon`whereuser_id='88888888'and`status`='1'GROUPBYdiscount_coupon_idhavingc>......
  • Spring + SpringMVC + SpringBoot + MyBatis 相关注解
    创建对象的:@Controller:放在类的上面,创建控制器对象,注入到容器中@RestController:放在类的上面,创建控制器对象,注入到容器中。作用:复合注解是@Controller,@ResponseBody,使用这个注解类的,里面的控制器方法的返回值都是数据@Service:放......
  • NET EF 参数化查询(LIKE / IN)
    原始数据:1.拼接SQL:容易注入2.参数化查询:2.1.等于+Like:2.2.等于+Like+ IN:2.2.1.结果:类似的参数传递,但是结果为02.2.2.分析:通过SQLServerProfile得到运行sql,发现IN的参数被处理成了一个字符串,类似于:WHERE[Key]IN('''01'',''11'',''21'�......
  • MySQL 查询按序累加数值
    Mysql假如我有一个表,有字段day,money,day记录我攒钱的第几天,money记录我当天攒的钱数,请写一个查询,返回我攒钱的天数,和这一天之前(包含这一天)一共攒的钱数SELECTday,money,(@cumulative_money:=@cumulative_money+money)AScumulative_moneyFROMyour_table_name,......
  • mongodb 查询操作实现原理
    MongoDB查询操作实现原理MongoDB是一种非关系型数据库,它以文档的形式存储数据,使用JSON风格的文档来表示数据。在MongoDB中,查询操作是非常重要和常用的操作之一。本文将介绍MongoDB查询操作的实现原理,并提供一些代码示例进行说明。查询操作的基本原理MongoDB提供了丰富......
  • mongodb 查询不带_id
    如何实现“MongoDB查询不带_id”作为一名经验丰富的开发者,你可以教会那些刚入行的小白如何在MongoDB数据库中实现查询不带_id。在本文中,我们将介绍整个过程,并附上具体代码和相应注释。步骤概览下面是实现“MongoDB查询不带_id”的整体步骤概览:步骤描述1连接到MongoDB......
  • mongoDB只查询一个字段
    MongoDB只查询一个字段在使用MongoDB进行数据查询操作时,有时我们只需要获取文档中的一个字段的值,而不需要获取整个文档的内容。这时,我们可以使用MongoDB的投影操作来仅查询一个字段,以提高查询效率和减少数据传输的大小。本文将介绍如何使用MongoDB进行只查询一个字段的操作,并提供......
  • mysql-查询数据库中所有的函数定义
    MySQL查询数据库中所有的函数定义在MySQL中,函数是一种自定义的代码块,它接受输入参数并返回一个结果。函数可以用于简化复杂的查询操作,提高代码的可重用性。在本文中,我们将介绍如何使用MySQL查询数据库中所有函数的定义。查询函数定义要查询数据库中所有的函数定义,我们可以使用......
  • mysql查询至少一门课程的成绩
    MySQL查询至少一门课程的成绩MySQL是一种常用的关系型数据库管理系统,广泛应用于各种Web应用和数据分析任务中。在进行数据查询时,我们经常需要筛选出满足一定条件的数据。本文将介绍如何使用MySQL查询至少一门课程的成绩,并提供相应的代码示例。数据库准备在开始之前,我们需要准备......
  • mysql查询正在执行的进程
    如何查询正在执行的MySQL进程1.流程概述查询正在执行的MySQL进程可以通过查看MySQL的信息模式(information_schema)来实现。主要的步骤包括连接到MySQL数据库、选择相关的数据库、执行查询语句,最后获取结果。下面是整个流程的步骤表格:步骤描述1连接到MySQL数据库2......