06. 流式查询
流式查询
流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果。流式查询的好处是能够降低内存使用。如果没有流式查询,我们想要从数据库取
MyBatis 流式查询接口
Cursor 是可关闭的;Cursor 是可遍历的。
除此之外,
- isOpen():用于在取数据之前判断
Cursor 对象是否是打开状态。只有当打开时Cursor 才能取数据; - isConsumed():用于判断查询结果是否全部取完。
- getCurrentIndex():返回已经获取了多少条数据
因为
cursor.forEach(rowObject -> {...});
但构建
@Mapper
public interface FooMapper {
@Select("select * from foo limit #{limit}")
Cursor<Foo> scan(@Param("limit") int limit);
}
方法
@GetMapping("foo/scan/0/{limit}")
public void scanFoo0(@PathVariable("limit") int limit) throws Exception {
try (Cursor<Foo> cursor = fooMapper.scan(limit)) { // 1
cursor.forEach(foo -> {}); // 2
}
}
上面的代码中,
java.lang.IllegalStateException: A Cursor is already closed.
这是因为我们前面说了在取数据的过程中需要保持数据库连接,而
SqlSessionFactory
我们可以用
@GetMapping("foo/scan/1/{limit}")
public void scanFoo1(@PathVariable("limit") int limit) throws Exception {
try (
SqlSession sqlSession = sqlSessionFactory.openSession(); // 1
Cursor<Foo> cursor =
sqlSession.getMapper(FooMapper.class).scan(limit) // 2
) {
cursor.forEach(foo -> { });
}
}
上面的代码中,
TransactionTemplate
在
@GetMapping("foo/scan/2/{limit}")
public void scanFoo2(@PathVariable("limit") int limit) throws Exception {
TransactionTemplate transactionTemplate =
new TransactionTemplate(transactionManager); // 1
transactionTemplate.execute(status -> { // 2
try (Cursor<Foo> cursor = fooMapper.scan(limit)) {
cursor.forEach(foo -> { });
} catch (IOException e) {
e.printStackTrace();
}
return null;
});
}
上面的代码中,
@Transactional 注解
这个本质上和方案二一样,代码如下:
@GetMapping("foo/scan/3/{limit}")
@Transactional
public void scanFoo3(@PathVariable("limit") int limit) throws Exception {
try (Cursor<Foo> cursor = fooMapper.scan(limit)) {
cursor.forEach(foo -> { });
}
}
它仅仅是在原来方法上面加了个