jdbc和mybatis的流式查询使用方法

作者:我想问问天 时间:2023-08-24 15:39:25 

导语:

有些时候我们所需要查询的数据量比较大,但是jvm内存又是有限制的,数据量过大会导致内存溢出。这个时候就可以使用流式查询,数据一条条的返回,处理完一条在拿下一条数据,这样每次在内存里面的数据其实很小,不会导致内存溢出。

本文里面会讲到jdbc的流式查询和mybatis的流式查询。

jdbc流式查询:

jdbc的流式查询需要在生成PreparedStatement的时候设置三个参数。如下:


PreparedStatement stmt = jdbcTemplate.getDataSource().getConnection().prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);

主要使用到的是java.sql.Connection的prepareStatement方法。


PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException;

resultSetType和resultSetConcurrency我们要分别设置为ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY。

还有就是fetchSize设置为Integer.MIN_VALUE,一开始比较疑惑为啥是这个值。后来发现代码里面对这个值其实是有特殊处理的。

这个是com.mysql.cj.jdbc.StatementImpl的setFetchSize方法。


@Override
  public void setFetchSize(int rows) throws SQLException {
      synchronized (checkClosed().getConnectionMutex()) {
          if (((rows < 0) && (rows != Integer.MIN_VALUE)) || ((this.maxRows > 0) && (rows > this.getMaxRows()))) {
              throw SQLError.createSQLException(Messages.getString("Statement.7"), MysqlErrorNumbers.SQL_STATE_ILLcom.mysql.cj.jdbc.StatementImpl的方法EGAL_ARGUMENT, getExceptionInterceptor());
          }
this.query.setResultFetchSize(rows);
      }
  }

resultSetType,有以下三种


/**
    * The constant indicating the type for a <code>ResultSet</code> object
    * whose cursor may move only forward.
    * @since 1.2
    */
   int TYPE_FORWARD_ONLY = 1003;
/**
    * The constant indicating the type for a <code>ResultSet</code> object
    * that is scrollable but generally not sensitive to changes to the data
    * that underlies the <code>ResultSet</code>.
    * @since 1.2
    */
   int TYPE_SCROLL_INSENSITIVE = 1004;
/**
    * The constant indicating the type for a <code>ResultSet</code> object
    * that is scrollable and generally sensitive to changes to the data
    * that underlies the <code>ResultSet</code>.
    * @since 1.2
    */
   int TYPE_SCROLL_SENSITIVE = 1005;

stmt = conn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);

resultSetConcurrency有以下两种,流式查询要设置为只读的,数据不会被更新。


/**
    * The constant indicating the concurrency mode for a
    * <code>ResultSet</code> object that may NOT be updated.
    * @since 1.2
    */
   int CONCUR_READ_ONLY = 1007;
/**
    * The constant indicating the concurrency mode for a
    * <code>ResultSet</code> object that may be updated.
    * @since 1.2
    */
   int CONCUR_UPDATABLE = 1008;

mybatis流式查询:

mapper中的代码:


@Select("select * from xxx order by xx desc")
@Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = Integer.MIN_VALUE)
@ResultType(XxxObject.class)
void queryStreamResult(ResultHandler<XxxObject> handler);

在查询方法上加入注解@Options和@ResultType。设置参数不用多说和上面jdbc的底层是一样的,参数值也一样。

只不过设置了@ResultType告诉程序应该要返回什么类型的对象。还有这个ResultHandler其实就是Consumer的函数式接口用来处理每一条返回的数据。

具体方法中的代码:


@Override
  public Boolean dealDataList() {
      mapper.queryStreamResult(resultContext -> {
          dealSingleData(resultContext.getResultObject().getUid());
      });
      return true;
  }

这里怎么使用每一条返回的数据只要在resultContext使用ResultObject就可以拿到上面mapper设置的XxxObject对象进行操作了。

来源:https://juejin.cn/post/7025246513622155272

标签:jdbc,mybatis,流式查询
0
投稿

猜你喜欢

  • dotnet如何将文件删除到回收站

    2023-04-23 13:52:09
  • Android自定义控件仿QQ编辑和选取圆形头像

    2022-11-10 09:40:37
  • Android巧用ViewPager实现左右循环滑动图片

    2021-07-13 16:32:32
  • 浅谈Spring中单例Bean是线程安全的吗

    2023-07-12 23:42:21
  • java实现基于TCP协议网络socket编程(C/S通信)

    2021-10-15 23:41:26
  • JavaWeb开发之【Tomcat 环境配置】MyEclipse+IDEA配置教程

    2022-05-04 12:50:18
  • C# 批处理调用方法

    2021-06-18 17:14:19
  • Java自定义实现链队列详解

    2023-06-22 12:47:31
  • Java concurrency之非公平锁_动力节点Java学院整理

    2022-07-31 22:04:37
  • SpringBoot 应用程序测试实现方案

    2021-12-18 04:27:54
  • Java设计模式之代理模式原理及实现代码分享

    2023-07-15 14:32:58
  • while和for可以相互转换的例子分享

    2023-08-23 02:17:46
  • java中switch选择语句代码详解

    2023-09-28 19:34:29
  • android用java动态增添删除修改布局

    2021-07-04 12:48:38
  • 详解MyBatis的Dao层实现和配置文件深入

    2022-07-26 02:29:17
  • resty mail的简单发送邮件方法

    2021-09-15 06:00:14
  • Java零基础教程之Windows下安装 JDK的方法图解

    2023-10-18 09:54:55
  • 巧用Spring中的@Order进行排序

    2023-07-13 05:53:48
  • Entity Framework模型优先与实体对象查询

    2022-11-18 07:19:36
  • Spring Cloud Config对特殊字符加密处理的方法详解

    2021-11-22 15:16:48
  • asp之家 软件编程 m.aspxhome.com