欢迎来到代码驿站!

JAVA代码

当前位置:首页 > 软件编程 > JAVA代码

Mybatis游标查询大量数据方式

时间:2022-11-21 08:26:49|栏目:JAVA代码|点击:

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)

上一篇:log4j2异步打印性能提升方式

栏    目:JAVA代码

下一篇:Spring深入讲解实现AOP的三种方式

本文标题:Mybatis游标查询大量数据方式

本文地址:http://www.codeinn.net/misctech/219519.html

推荐教程

广告投放 | 联系我们 | 版权申明

重要申明:本站所有的文章、图片、评论等,均由网友发表或上传并维护或收集自网络,属个人行为,与本站立场无关。

如果侵犯了您的权利,请与我们联系,我们将在24小时内进行处理、任何非本站因素导致的法律后果,本站均不负任何责任。

联系QQ:914707363 | 邮箱:codeinn#126.com(#换成@)

Copyright © 2020 代码驿站 版权所有