新技能 MyBatis 千万数据表,快速分页!
大家好,我是磊哥。
MyBatis 流式查询接口
org.apache.ibatis.cursor.Cursor
java.io.Closeable
和 java.lang.Iterable
接口,由此可知:isOpen()
:用于在取数据之前判断 Cursor 对象是否是打开状态。只有当打开时 Cursor 才能取数据;isConsumed()
:用于判断查询结果是否全部取完。getCurrentIndex()
:返回已经获取了多少条数据cursor.forEach(rowObject -> {...});
但构建 Cursor 的过程不简单
@Mapper
publicinterfaceFooMapper{
@Select("select * from foo limit #{limit}")
Cursor<Foo> scan(@Param("limit") int limit);
}
@GetMapping("foo/scan/0/{limit}")
publicvoid scanFoo0(@PathVariable("limit") int limit) throwsException{
try(Cursor<Foo> cursor = fooMapper.scan(limit)) { // 1
cursor.forEach(foo -> {}); // 2
}
}
java.lang.IllegalStateException: A Cursoris already closed.
方案一:SqlSessionFactory
@GetMapping("foo/scan/1/{limit}")
publicvoid scanFoo1(@PathVariable("limit") int limit) throwsException{
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}")
publicvoid scanFoo2(@PathVariable("limit") int limit) throwsException{
TransactionTemplate transactionTemplate =
newTransactionTemplate(transactionManager); // 1
transactionTemplate.execute(status -> { // 2
try(Cursor<Foo> cursor = fooMapper.scan(limit)) {
cursor.forEach(foo -> { });
} catch(IOException e) {
e.printStackTrace();
}
returnnull;
});
}
方案三:@Transactional 注解
@GetMapping("foo/scan/3/{limit}")
@Transactional
publicvoid scanFoo3(@PathVariable("limit") int limit) throwsException{
try(Cursor<Foo> cursor = fooMapper.scan(limit)) {
cursor.forEach(foo -> { });
}
}
@Transactional
注解。这个方案看上去最简洁,但请注意 Spring 框架当中注解使用的坑:只在外部调用时生效。在当前类中调用这个方法,依旧会报错。近期技术热文
往期推荐
第3版:互联网大厂面试题
包括 Java 集合、JVM、多线程、并发编程、设计模式、算法调优、Spring全家桶、Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、MongoDB、Redis、MySQL、RabbitMQ、Kafka、Linux、Netty、Tomcat、Python、HTML、CSS、Vue、React、JavaScript、Android 大数据、阿里巴巴等大厂面试题等、等技术栈!
阅读原文: 高清 7701页大厂面试题 PDF