Mybatis游标查询大量数据方式

 更新时间:2022年2月8日 09:48  点击:505 作者:绊脚石0320

Mybatis游标查询大量数据

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

mapper层

  • 使用Cursor类型进行数据接收
  • @Options,fetchSize设置为Integer最小值
  • @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);

service层 

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

数据处理

forEach方式

domainList.forEach(illegalDomain -> {
    //处理逻辑,根据业务需求自行完成
    Future<IcpStatusVo> future = checkIcpThreadPool.submit(new IcpCheckThread(illegalDomain.getDomain(), configMap));
    results.add(future);
});

迭代器 

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);
}

资源释放

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

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

Mybatis游标使用总结

当查询百万级的数据的时候,查询出所有数据并放入内存中时会发生OOM(OutOfMemoryException),使用游标可以节省内存的消耗,不需要一次性取出所有数据,可以进行逐条处理或逐条取出部分批量处理,在此场景下就可以使用游标的概念来解决这个问题。

什么是游标

游标(Cursor)是处理数据的一种方法,为了查看或者处理结果集中的数据,游标提供了在结果集中一次一行或者多行前进或向后浏览数据的能力。

Demo:

// 第一种
@Options(resultSetType = ResultSetType.FORWARD_ONLY)
@Select("SELECT * FROM department WHERE status = 0")
List<DepartmentEntity> queryDepartmentAll();
 
// 第二种 在Mybatis-3.4.0版本中,不支持@select注解,在3.4.1版本中已经修复:
@Options(resultSetType = ResultSetType.FORWARD_ONLY)
@Select("SELECT * FROM department WHERE status = 0")
Cursor<Employee> cursorQueryDepartmentAll();

@Service
public class DepartmentServiceImpl implements DepartmentService { 
    private static final Logger LOG = LoggerFactory.getLogger(DepartmentServiceImpl.class);
 
    @Autowired
    private DepartmentDao departmentDao;
 
    @Autowired
    private SqlSessionTemplate sqlSessionTemplate; 
    public List<DepartmentDTO> getDepartmentList(DepartmentSearchParam param) {
        Cursor<Object> cursor = null;
        SqlSession sqlSession = null;
        try {
            sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession();
            cursor = sqlSession.selectCursor(DepartmentDao.class.getName() + ".queryDepartmentAll");
            cursor.forEach(e -> {
                // 处理逻辑
            });
           // 也可以使用迭代器:Iterator<Object> iterator = cursor.iterator();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != cursor) {
                try {
                    cursor.close();
                } catch (Exception e) {
                    LOG.error(e.getMessage(), e);
                }
            }
            if (null != sqlSession) {
                try {
                    sqlSession.close();
                } catch (Exception e) {
                    LOG.error(e.getMessage(), e);
                }
            }
        }
    }
}

  • ResultSet.TYPE_FORWORD_ONLY 结果集的游标只能向下滚动。
  • ResultSet.TYPE_SCROLL_INSENSITIVE 结果集的游标可以上下移动,当数据库变化时,当前结果集不变。
  • ResultSet.TYPE_SCROLL_SENSITIVE 返回可滚动的结果集,当数据库变化时,当前结果集同步改变。 

注意:游标是可以前后移动的。如果resultSetType = TYPE_SCROLL_INSENSITIVE ,就是设置游标就可以前后移动。

Mybatis为了保证可以前后移动,Mybatis会把之前查询的数据一直保存在内存中。

所以并不能根本解决OOM,所以我们这里需要设置为@Options(resultSetType = ResultSetType.FORWARD_ONLY)(其实默认就是ResultSetType.FORWARD_ONLY)

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

原文出处:https://blog.csdn.net/qq_42594278/article/details/106633917

[!--infotagslink--]

相关文章

  • C#连接SQL数据库和查询数据功能的操作技巧

    本文给大家分享C#连接SQL数据库和查询数据功能的操作技巧,本文通过图文并茂的形式给大家介绍的非常详细,需要的朋友参考下吧...2021-05-17
  • Mybatis Plus select 实现只查询部分字段

    这篇文章主要介绍了Mybatis Plus select 实现只查询部分字段的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-09-01
  • php简单数据操作的实例

    最基础的对数据的增加删除修改操作实例,菜鸟们收了吧...2013-09-26
  • 解决Mybatis 大数据量的批量insert问题

    这篇文章主要介绍了解决Mybatis 大数据量的批量insert问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-09
  • Antd-vue Table组件添加Click事件,实现点击某行数据教程

    这篇文章主要介绍了Antd-vue Table组件添加Click事件,实现点击某行数据教程,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-11-17
  • 详解如何清理redis集群的所有数据

    这篇文章主要介绍了详解如何清理redis集群的所有数据,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-18
  • mybatis的Configuration详解

    这篇文章主要介绍了mybatis的Configuration详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-04
  • vue 获取到数据但却渲染不到页面上的解决方法

    这篇文章主要介绍了vue 获取到数据但却渲染不到页面上的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-19
  • mybatis 返回Integer,Double,String等类型的数据操作

    这篇文章主要介绍了mybatis 返回Integer,Double,String等类型的数据操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-11-25
  • php把读取xml 文档并转换成json数据代码

    在php中解析xml文档用专门的函数domdocument来处理,把json在php中也有相关的处理函数,我们要把数据xml 数据存到一个数据再用json_encode直接换成json数据就OK了。...2016-11-25
  • mybatis-plus 处理大数据插入太慢的解决

    这篇文章主要介绍了mybatis-plus 处理大数据插入太慢的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-12-18
  • MyBatisPlus-QueryWrapper多条件查询及修改方式

    这篇文章主要介绍了MyBatisPlus-QueryWrapper多条件查询及修改方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2022-06-27
  • postgresql数据添加两个字段联合唯一的操作

    这篇文章主要介绍了postgresql数据添加两个字段联合唯一的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-02-04
  • Oracle使用like查询时对下划线的处理方法

    这篇文章主要介绍了Oracle使用like查询时对下划线的处理方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-03-16
  • 解决mybatis-plus 查询耗时慢的问题

    这篇文章主要介绍了解决mybatis-plus 查询耗时慢的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-07-04
  • Vue生命周期activated之返回上一页不重新请求数据操作

    这篇文章主要介绍了Vue生命周期activated之返回上一页不重新请求数据操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-26
  • c# socket网络编程接收发送数据示例代码

    这篇文章主要介绍了c# socket网络编程,server端接收,client端发送数据,大家参考使用吧...2020-06-25
  • MyBatis-Plus的物理删除和逻辑删除(使用场景)

    数据库中的数据删除会分为两种:物理删除 和 逻辑删除,接下来通过本文给大家介绍MyBatis-Plus的物理删除和逻辑删除使用场景分析,感兴趣的朋友一起看看吧...2021-09-25
  • 解决vue watch数据的方法被调用了两次的问题

    这篇文章主要介绍了解决vue watch数据的方法被调用了两次的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-11-07
  • vue 数据(data)赋值问题的解决方案

    这篇文章主要介绍了vue 数据(data)赋值问题的解决方案,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-29