这篇文章主要讲解了“Mybatis游标查询大量数据的方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Mybatis游标查询大量数据的方法是什么”吧!
对大量数据进行处理时,为防止内存泄漏情况发生,所以采用mybatis plus游标方式进行数据查询处理,当查询百万级的数据的时候,使用游标可以节省内存的消耗,不需要一次性取出所有数据,可以进行逐条处理或逐条取出部分批量处理
使用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);
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(); } } }
当查询百万级的数据的时候,查询出所有数据并放入内存中时会发生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)
感谢各位的阅读,以上就是“Mybatis游标查询大量数据的方法是什么”的内容了,经过本文的学习后,相信大家对Mybatis游标查询大量数据的方法是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。