0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

MyBatis流式查询轻松帮你解决分页慢的问题

5jek_harmonyos 来源:思否开发者社区 作者:捏造的信仰 2021-08-04 15:52 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

作者丨捏造的信仰

segmentfault.com/a/1190000022478915

Part1基本概念

流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果。流式查询的好处是能够降低内存使用。

如果没有流式查询,我们想要从数据库取 1000 万条记录而又没有足够的内存时,就不得不分页查询,而分页查询效率取决于表设计,如果设计的不好,就无法执行高效的分页查询。因此流式查询是一个数据库访问框架必须具备的功能。

流式查询的过程当中,数据库连接是保持打开状态的,因此要注意的是:执行一个流式查询后,数据库访问框架就不负责关闭数据库连接了,需要应用在取完数据后自己关闭。

Part2MyBatis 流式查询接口

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

Cursor 是可关闭的。实际上当关闭 Cursor 时,也一并将数据库连接关闭了;

Cursor 是可遍历的。

除此之外,Cursor 还提供了三个方法:

isOpen():用于在取数据之前判断 Cursor 对象是否是打开状态。只有当打开时 Cursor 才能取数据;

isConsumed():用于判断查询结果是否全部取完;

getCurrentIndex():返回已经获取了多少条数据。

因为 Cursor 实现了迭代器接口,因此在实际使用当中,从 Cursor 取数据非常简单:

try(Cursor cursor = mapper.querySomeData()) {

cursor.forEach(rowObject -》 {

// 。。。

});

}

使用 try-resource 方式可以令 Cursor 自动关闭。

Part3但构建 Cursor 的过程不简单

我们举个实际例子。下面是一个 Mapper 类:

@Mapper

public interface FooMapper {

@Select(“select * from foo limit #{limit}”)

Cursor《Foo》 scan(@Param(“limit”) int limit);

}

方法 scan() 是一个非常简单的查询。我们在定义这个方时,指定返回值为 Cursor 类型,MyBatis 就明白这个查询方法是一个流式查询。

然后我们再写一个 SpringMVC Controller 方法来调用 Mapper(无关的代码已经省略):

@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

}

}

假设 fooMapper 是 @Autowired 进来的。注释 1 处是获取 Cursor 对象并保证它能最后关闭;2 处则是从 cursor 中取数据。

上面的代码看上去没什么问题,但是执行 scanFoo0(int) 时会报错:

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

这是因为我们前面说了在取数据的过程中需要保持数据库连接,而 Mapper 方法通常在执行完后连接就关闭了,因此 Cusor 也一并关闭了。

所以,解决这个问题的思路不复杂,保持数据库连接打开即可。我们至少有三种方案可选。

方案一:SqlSessionFactory

我们可以用 SqlSessionFactory 来手工打开数据库连接,将 Controller 方法修改如下:

@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 -》 { });

}

}

上面的代码中,1 处我们开启了一个 SqlSession (实际上也代表了一个数据库连接),并保证它最后能关闭;2 处我们使用 SqlSession 来获得 Mapper 对象。这样才能保证得到的 Cursor 对象是打开状态的。

方案二:TransactionTemplate

在 Spring 中,我们可以用 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;

});

}

上面的代码中,1 处我们创建了一个 TransactionTemplate 对象(此处 transactionManager 是怎么来的不用多解释,本文假设读者对 Spring 数据库事务的使用比较熟悉了),2 处执行数据库事务,而数据库事务的内容则是调用 Mapper 对象的流式查询。注意这里的 Mapper 对象无需通过 SqlSession 创建。

方案三:@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 -》 { });

}

}

它仅仅是在原来方法上面加了个 @Transactional 注解。这个方案看上去最简洁,但请注意 Spring 框架当中注解使用的坑:只在外部调用时生效。在当前类中调用这个方法,依旧会报错。

以上是三种实现 MyBatis 流式查询的方法。

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • mybatis
    +关注

    关注

    0

    文章

    64

    浏览量

    7081

原文标题:还在担心分页慢吗? MyBatis 流式查询解决你的烦恼

文章出处:【微信号:harmonyos_developer,微信公众号:harmonyos_developer】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    微店商品列表API,轻松采集商品列表数据

    微店商品列表API是微店开放平台提供的核心接口,主要用于获取指定店铺的商品列表数据。该接口支持分页查询、条件筛选和排序功能,适用于电商管理系统、竞品分析和多平台展示等场景。 一、接口概述 1.
    的头像 发表于 12-01 14:32 166次阅读

    商品类目属性查询接口技术实现详解

    ​   一、接口核心功能 该接口用于查询电商系统中商品类目的属性信息,支持: 按类目ID查询属性集合 按属性类型过滤(关键属性$K$、销售属性$S$、普通属性$N$) 分页返回属性数据 多语言属性名
    的头像 发表于 10-11 15:43 261次阅读
    商品类目属性<b class='flag-5'>查询</b>接口技术实现详解

    数据库查询分析与SQL优化实战技巧

    今天,我将分享我在处理数千次数据库性能问题中积累的实战经验,帮助你系统掌握查询分析与SQL优化的核心技巧。无论你是刚入门的运维新手,还是有一定经验的工程师,这篇文章都将为你提供实用的解决方案。
    的头像 发表于 09-08 09:34 630次阅读

    MySQL查询优化案例

    凌晨3点,手机疯狂震动。监控告警显示:核心业务接口响应时间超过20秒,用户投诉如潮水般涌来。这是每个运维工程师的噩梦时刻。
    的头像 发表于 08-27 14:49 484次阅读

    MySQL查询终极优化指南

    作为一名在生产环境摸爬滚打多年的运维工程师,我见过太多因为查询导致的线上故障。今天分享一套经过实战检验的MySQL查询分析与索引优化方法论,帮你
    的头像 发表于 08-13 15:55 659次阅读

    简要分析限流式保护器在某无人驾驶汽车充电站的应用

    摘 要:交流充电桩俗称“充桩”,固定安装在电动汽车外、与交流电网连接,国标采用 220V单相交流电,为电动汽车车载充电机(即固定安装在电动汽车上的充电机)提供交流电源的供电装置。国家标准
    的头像 发表于 07-08 14:28 400次阅读
    简要分析限<b class='flag-5'>流式</b>保护器在某无人驾驶汽车充电站的应用

    ASCP310系列电气防火限流式保护器安装使用说明书 V1.2

    ASCP310 系列电气防火限流式保护器是安科瑞电气专为中低压配电系统设计的智能保护设备,主要应用于电动汽车充电站、工业配电、商业建筑等场景。针对传统断路器短路响应、电弧危害大等问题,该保护器以微秒级速度快速限制短路电流,实现灭弧保护,显著降低电气火灾风险,保障用电安全
    发表于 05-17 17:32 2次下载

    充电桩用限流式保护器怎么选择?

    简婷 安科瑞电气股份有限公司 上海嘉定  201801 技术支持18701998775  电气防火限流式保护器    电气防火限流式保护器是一种电气保护设备,通常用于防止电气设备过载、短路、接地故障
    的头像 发表于 04-11 13:10 793次阅读
    充电桩用限<b class='flag-5'>流式</b>保护器怎么选择?

    IP地址查询技术

    IP查询****的价值 根据2023年国际互联网数据中心统计,全球每天产生的IP查询请求超过50亿次,这一数字就能够清晰的看出广大群众对于IP查询技术的需求以及它的价值。 而传统IP查询
    的头像 发表于 02-12 11:13 731次阅读
    IP地址<b class='flag-5'>查询</b>技术

    一台“两栖”的光谱流式分析仪----CytoFLEX mosaic

    上海2025年2月6日 /美通社/ -- 贝克曼库尔特生命科学正式推出CytoFLEX家族新成员:CytoFLEX mosaic光谱流式分析仪 它是一款具备"两栖"能力的流式
    的头像 发表于 02-06 20:03 602次阅读
    一台“两栖”的光谱<b class='flag-5'>流式</b>分析仪----CytoFLEX mosaic

    一种轻量分表方案-MyBatis拦截器分表实践

    作者:京东零售 张均杰 背景 部门内有一些亿级别核心业务表增速非常快,增量日均100W,但线上业务只依赖近一周的数据。随着数据量的迅速增长,SQL频发,数据库性能下降,系统稳定性受到严重影响。本篇
    的头像 发表于 01-23 17:38 656次阅读

    电气防火限流式保护器是如何运用在汽车充电桩中?

    1 摘要 随着世界的发展,环境保护成为整个人类命运共同体的任务。全世界各国政府也为此提供优惠政策鼓励电动车科技的普及。交流充电桩俗称“充桩”,固定安装在电动汽车外、与交流电网连接,国标采用
    的头像 发表于 01-16 10:57 924次阅读
    电气防火限<b class='flag-5'>流式</b>保护器是如何运用在汽车充电桩中?

    老旧小区充电桩限流式保护器的应用

    摘要  ​随着城市化进程的推进,老旧小区的电气设施逐渐显现出无法满足现代用电需求的局面。特别是在老旧小区进行用电改造时,电气安全问题尤为突出。传统的电气保护设备在短路和过载保护方面存在响应、寿命短
    的头像 发表于 01-06 14:34 864次阅读
    老旧小区充电桩限<b class='flag-5'>流式</b>保护器的应用

    浅谈电气防火限流式保护器在汽车充电桩应用场景的应用

    安科瑞徐赟杰18706165067 摘要 随着世界的发展,环境保护成为整个人类命运共同体的任务。全世界各国政府也为此提供优惠政策鼓励电动车科技的普及。交流充电桩俗称“充桩”,固定安装在电动汽车
    的头像 发表于 12-23 09:26 1036次阅读
    浅谈电气防火限<b class='flag-5'>流式</b>保护器在汽车充电桩应用场景的应用

    Mybatis 拦截器实现单数据源内多数据库切换

    作者:京东保险 王奕龙 物流的分拣业务在某些分拣场地只有一个数据源,因为数据量比较大,将所有数据存在一张表内查询速度,也为了做不同设备数据的分库管理,便在这个数据源内创建了多个不同库名但表完全相同
    的头像 发表于 12-12 10:23 1604次阅读