Mybatis 流式查询

Mybatis 流式查询

简介:流式查询指的是数据库查询成功后,返回一个迭代器,而不是返回一个集合,每次从迭代器取一条查询结果放到缓存器中,当缓存器满了之后,放到结果集中,清空缓存,按游标位置继续读取数据。流式查询的好处是能够降低内存使用,防止java内存溢出(OOM,全称OUT OF MEMORY)。

原理

和StringBuffer的原理相似,Mybatis 流式查询是逐条将读取的数据放到resultset结果集中

流程

  1. client发送select查询请求给Server
  2. Server根据条件筛选符合条件的记录,然后就会把记录发送到buffer
  3. buffer满了就flush缓存(这里要注意的是如果client的buffer缓存满了,那么Server的发送就会阻塞,直到client的buffer缓存空闲。),通过网络发送到client的buffer缓存
  4. 当不用游标时候(缓存满了的时候),MySqI就会从buffer缓存里面逐个读取记录到resultset。

就这样client 从自己的buffer缓存读取数据到resultset,同时Server端不断通过网络向client的buffer缓存发送数据,直到所有记录都放到了resultset。(操作期间数据库一定要持续连接,操作完成后必须断开数据库连接,减少资源浪费)

在这里插入图片描述

关联的接口

MyBatis提供了一个叫 org.apache.ibatis.cursor.Cursor 的接口类用于流式查询,这个接口继承了 java.io.Closeable 和 java.lang.Iterable 接口,由此可知:

  1. Cursor 是可关闭的
  2. Cursor 是可遍历的
@Mapper
public interface TestMapper {
    @Select("select * from test")
    Cursor scan();
}

从以上代码可知返回值为Cursor,但是需要注意的是,每此对数据库进行操作的时候,数据库就会关闭,这就会导致报错,原因是因为Cursor必须持续对数据库进行操作,而且操作完成之后还需要对数据库进行关闭

以下为报错信息:

java.lang.IllegalStateException: A Cursor is already closed.

流式查询报错解决方式

在方法上添加@Transactional 注解(注解可加在Controller、ServiceImpl的方法上)

@GetMapping("test/scan")
@Transactional
public void scanTest() throws Exception {
    try {
        Cursor cursor = testMapper.scan();
        cursor.forEach(data -> { });
    }
}

需要注意的是,@Transactional 注解使用的方法必须为对外的接口,而不是内部调用的方法,否则依旧会报错。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值