千家信息网

Mybatis游标查询大量数据的方法是什么

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章主要讲解了"Mybatis游标查询大量数据的方法是什么",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"Mybatis游标查询大量数据的方法是什么
千家信息网最后更新 2026年11月02日Mybatis游标查询大量数据的方法是什么

这篇文章主要讲解了"Mybatis游标查询大量数据的方法是什么",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"Mybatis游标查询大量数据的方法是什么"吧!

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 getDayJobDomain(@Param("icpstatus") Integer icpstatus);

service层

Cursor domainList = illegalDomainMapper.getDayJobDomain(1);

数据处理

forEach方式

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

迭代器

Iterator iter = domainList.iterator();while (iter.hasNext()) {                        //处理逻辑,根据业务需求自行完成    Future 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 queryDepartmentAll(); // 第二种 在Mybatis-3.4.0版本中,不支持@select注解,在3.4.1版本中已经修复:@Options(resultSetType = ResultSetType.FORWARD_ONLY)@Select("SELECT * FROM department WHERE status = 0")Cursor cursorQueryDepartmentAll();
@Servicepublic class DepartmentServiceImpl implements DepartmentService {     private static final Logger LOG = LoggerFactory.getLogger(DepartmentServiceImpl.class);     @Autowired    private DepartmentDao departmentDao;     @Autowired    private SqlSessionTemplate sqlSessionTemplate;     public List getDepartmentList(DepartmentSearchParam param) {        Cursor cursor = null;        SqlSession sqlSession = null;        try {            sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession();            cursor = sqlSession.selectCursor(DepartmentDao.class.getName() + ".queryDepartmentAll");            cursor.forEach(e -> {                // 处理逻辑            });           // 也可以使用迭代器:Iterator 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)

感谢各位的阅读,以上就是"Mybatis游标查询大量数据的方法是什么"的内容了,经过本文的学习后,相信大家对Mybatis游标查询大量数据的方法是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

0