Mybatis 流式查询

文章目录

  • 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 流式查询_第1张图片

关联的接口

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 注解使用的方法必须为对外的接口,而不是内部调用的方法,否则依旧会报错。

你可能感兴趣的:(java)