JDBC流式读取
Posted 唐微港
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDBC流式读取相关的知识,希望对你有一定的参考价值。
业务场景
-
在做数据库的相关开发的时候,可能有人面对过这些场景,从一个数据库把大数据量读取出来存放到另外一个数据库、做大数据量的报表、将大数据量的数据读取出来推送到接口。
-
因为是大数据量,所以如果直接读取可能会存在OOM的问题,或者直接卡顿,因为使用JDBC连接数据库读取大数据量时候,所有的数据是直接从数据库服务端加载进入了客户端,所以内存占用过大,而且result.next()方法会阻塞。
解决方式
分页
上面的这种情况或许有人会说,数据量大那可以使用分页的方式,的确,甚至可以使用框架的分页,例如mybatis-plus这些。可是存在的问题是,这种方式一样会效率低下,而且上面的场景中可能还没用具体的对象进行关系映射
。并且其他框架底层也是基于JDBC的这种方式构建的。
所以这里就只能考虑使用JDBC的方式获取表数据。
流式读取
在使用JDBC连接获取数据时,JDBC为我们提供了一种获取数据的方式叫做流式读取,这个有些类似于java8中的stream流。
preparedStatement = connctObj.prepareStatement(strSql, ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY);
preparedStatement.setFetchSize(1000);
preparedStatement.setFetchDirection(ResultSet.FETCH_REVERSE);
resultSet = preparedStatement.executeQuery();
如上所示其实就是在prepareStatement中加入了ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_READ_ONLY
,参数中使用了preparedStatement.setFetchSize(1000);和preparedStatement.setFetchDirection(ResultSet.FETCH_REVERSE);
如果这些参数没给JDBC就默认没有开启流式读取,给了setFetchSize,ResultSet.TYPE_FORWARD_ONLY和ResultSet.CONCUR_READ_ONLY就表示开启了流式读取,这样在获取到resultSet中查询结果的时候就不会一次性全部放入内存中,而且效率也比较可观。
注意
preparedStatement.setFetchSize(1000);
中的1000最初默认是Integer.MIN_VALUE,例如preparedStatement.setFetchSize(Integer.MIN_VALUE);
但是这个是表示每次获取的长度,所以可以换成具体的数字,那个合适还得自己根据实际查询的量拿去试试。
以上是关于JDBC流式读取的主要内容,如果未能解决你的问题,请参考以下文章