1、流式查询简介
流式处理在大数据方面应用比较广泛。随着数据的爆发式增长,流式处理的方式也被应用到日常的工具中,如JDK的对于集合处理的Stream流、Redis5.0新增的数据结构Stream专门来处理消息等。
流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果。流式查询的好处是能够降低内存使用。
今天要分享的是Mybaits的流式查询。Mybatis流式查询通过使用游标一次处理一条数据的方式,减少了内存的占用,从而提高了大数据量查询的效率。
2、Mybaits流式查询
Mybaits在3.4.0版本增加了流式查询也就是游标Cursor。更新日志传动门,Issues · mybatis/mybatis-3 · GitHub

2.1 游标简介
游标的使用和List一样,只不过返回的结果不同。

游标继承
Closeable,Iterable接口,所以游标是可关闭、可遍历的。包含三个方法:
isOpen游标的开关是否打开
isConsumed通过游标是否将拉取的数据消费完,也就是是否将数据全部取完。
getCurrentIndex获取当前数据的位置,位置是从0开始的。

2.2 游标的使用
定义简单的查询方法,这里使用注解
@Select的方式代替Xml,方便测试。
@Select("select * from logan_log.logan_login")
Cursor<LoganLogin> testCursorQuery();
编写测试类。因为游标是可关闭的,所以使用完之后要想流一样关闭掉。这里采用
try-resource的方式简化流的关闭。
@Test
void testCursorSql() {
try (Cursor<LoganLogin> cursor = loganLoginMapper.testCursorQuery()) {
cursor.forEach((ll) -> {
System.out.println("ll:" + JSON.toJSONString(ll));
System.out.println("ll cursor:" + cursor.getCurrentIndex());
});
} catch (IOException e) {
throw new RuntimeException(e);
}
}
处理结果,报错了。。。

原因分析:
-
A Cursor is already closed.还没有处理数据,查询完数据之后游标被关闭了。 -
由于Mybatis帮我们做了自动事务的提交。查询完毕之后就会提交事务关闭连接,游标自然也被关闭了,就会出现这样的问题。游标需要占用数据库的连接,然后逐条的将数据返回的。
解决方案:
-
将整个方法放在一个事务里面,处理完数据之后在提交事务。比较暴力的解决方案就是使用声明式事务
@Transactional。大事务的处理可能会影响业务的并发。 -
采用小颗粒度的编程式事务
TransactionTemplate,只针对流式查询的结果包装到一个事务里面即可。 -
也可以采用手动提交事务,使用
SqlSessionFactory手动建立连接和关闭。
编程式事务解决问题可能更方便一些,所以采用编程式事务的方法解决。
@Test
void testCursorSql2() {
transactionTemplate.execute(new TransactionCallb

本文介绍了流式查询在大数据场景中的应用,特别是Mybatis3.4.0版本引入的游标功能,通过游标实现内存优化,以及如何在Mybatis-Plus中使用流式查询和ResultHandler进行数据处理。
最低0.47元/天 解锁文章
357

被折叠的 条评论
为什么被折叠?



