华新科 Walsin · 产品与技术资料捷比信主站 · 综合产品与服务
华新科 Walsin电容、电阻与电感
捷比信产品咨询0797-4282799

MyBatis数千万的数据查询解决方案避免了OOM

流查询意味着在成功查询之后,应用程序每次都从迭代器中获取一个查询结果,而不是返回一个集合,而是一个迭代器。流查询的优点是它可以减少内存使用量。
如果没有流查询,则当我们想从数据库中获取1000万条记录并且没有足够的内存时,我们必须进行页面查询,而页面查询的效率取决于表的设计。如果设计不好,将无法执行有效的分页查询。
因此,流查询是数据库访问框架的必要功能。在流查询的过程中,数据库连接保持打开状态,因此应注意,在执行流查询后,数据库访问框架不负责关闭数据库连接,应用程序需要在获取数据后将其关闭。
。 MyBatis流查询界面MyBatis提供了一个名为org.apache.ibatis.cursor.Cursor的接口类,用于流查询。
此接口继承java.io.Closeable和java.lang.Iterable接口。从中我们可以看到:游标可以关闭;游标是可遍历的。
此外,Cursor还提供了三种方法:isOpen():用于在获取数据之前确定Cursor对象是否处于打开状态。游标只能在打开时才能获取数据。
isConsumed():用于判断查询结果是否全部被获取。 getCurrentIndex():返回已获取多少数据。
因为Cursor实现了迭代器接口,所以在实际使用中从Cursor中获取数据非常简单:cursor.forEach(rowObject& nbsp;-& nbsp; {...});但是构建游标的过程并不简单。让我们举一个实际的例子。
这是一个Mapper类:@Mapper公共接口FooMapper {@Select(“ select& nbsp; *& nbsp; foo& nbsp; limit& nbsp;#{limit}”)Cursorscan(@Param( “ limit()” int limit);}方法scan()是一个非常简单的查询。通过将Mapper方法的返回值指定为Cursor类型,MyBatis知道此查询方法是流查询。
然后,我们编写另一个SpringMVC Controller方法来调用Mapper(不相关的代码已被省略):@GetMapping(“ foo / scan / 0 / {limit}”)public void scanFoo0(@PathVariable(“ limit”)int limit)抛出异常{}); //& nbsp; 2}}在上面的代码中,fooMapper由@Autowired传入。注意1调用scan方法获取Cursor对象并确保最终可以将其关闭;注意2是从游标中获取数据。
上面的代码似乎没问题,但是在执行scanFoo0()时将报告错误:java.lang.IllegalStateException:Cursor& is& nbsp;已经关闭。这是因为我们前面说过,在获取数据的过程中需要保留它。
数据库连接,Mapper方法通常在执行后关闭连接,因此Cusor也被关闭。因此,解决此问题的想法并不复杂,只需保持数据库连接打开即可。
我们至少有三个选择。解决方案1:SqlSessionFactory我们可以使用SqlSessionFactory手动打开数据库连接,如下修改Controller方法:@GetMapping(“ foo / scan / 1 / {limit}”)public void scanFoo1(@PathVariable(“ limit”); )int limit)引发异常{try(& nbsp;& nbsp;& nbsp;& nbsp;& nbsp;& nbsp;& nbsp;& nbsp; SqlSession& nbsp; sqlSession& nbsp; = & nbsp; sqlSessionFactory.openSession(); //  1游标  =& nbsp;& nbsp;& nbsp;& nbsp;& nbsp;& nbsp;& nbsp; & nbsp;& nbsp;& nbsp;& nbsp;& nbsp;& nbsp;& nbsp; sqlSession.getMapper(FooMapper.class).scan(limit)& nbsp;& ;  //& nbsp; 2& nbsp;& nbsp;& nbsp;){& nbsp;& nbsp;& nbsp;& nbsp;& nbsp ;& nbsp;& nbsp; cursor.forEach(foo& nbsp;-& nbsp; {& nbsp;});& nbsp;& nbsp;& nbsp; & nbsp;}}上面的代码首先,我们打开了一个SqlSess离子(实际上代表数据库连接),并确保可以在最后关闭它;其次,我们使用SqlSession来获取Mapper对象。
这样,可以确保获得的光标对象是打开的。解决方案2:TransactionTemplate在Spring中,我们可以使用TransactionTemplate执行数据库事务,在此期间还将打开数据库连接。
代码如下:@GetMapping(“ foo / scan / 2 / {limit}”)public void scanFoo2(@PathVariable(“ limit”)int limit)引发异常{& nbsp;& nbsp;& amp; ; nbsp;& nbsp; TransactionTemplate& nbsp; transactionTemplate  =新的TransactionTemplate(transactionManager); //  1 transactionTemplate.execute(status& n。

相关资料

什么是开关电源芯片?推出开关电源芯片U6201的九大优势!国际电路板展览会-深圳和PCB行业关注“ 5高”主题一起!Vishay推出了一种新的通孔电感器,该电感器的外形尺寸为1500小,饱和电流为420 ABMS锂电池保护板值得学习。你知道它的工作原理和特点吗?Vivo S7t手机详细规格一目了然贿赂1.75亿元!三星电子负责人在法庭上被捕让我们来看看人们近年来设计的各种酷炫的无人机创意刷新理解!进程和线程的简单说明在空调系统中引入两管/三管/四管STM32时钟分析上海三大运营商免费升级到100M宽带计划中兴通讯与银联数据成立金融行业首个5G消息实验室成百上千的无人机“失控而撞上建筑物”,这是程序员编写的错误吗?想要高性能的数字温度传感器吗? PCT2075不妨了解一下!基本介绍:您是否了解纸,聚苯乙烯,薄膜,漆膜和云母电容器?民生银行,兴业银行和其他6家银行应用程序涉嫌违反隐私规定,监管部门强调以标准化方式使用数据微信小程序实况转播销售测试,谁将成为下一个李嘉琪Synopsys:以DevOps的速度创建安全的软件我的大脑敞开着:这样可以调试定位GPS北斗信号吗?基于RTE创建项目时必须注意Keil for ARM版本5.33