默认情况下executeQuery会一次性拉取所有的查询数据,但是当遇到大数据量时,非常容易造成OOM。这种场景需要设置fetchSize,执行的时候会先拉取第一批数据,之后next结束一批数据后再重新拉取下一批数据。
实例代码
try {
if (null == conn) {
conn = jdbcUtil.getConnection();
}
java.sql.Date startTime = CommonUtils.isNotNull(dataAnalysisReport.getRecordTimeStart()) ? new java.sql.Date(dataAnalysisReport.getRecordTimeStart().getTime()) : null;
java.sql.Date endTime = CommonUtils.isNotNull(dataAnalysisReport.getRecordTimeEnd()) ? new java.sql.Date(dataAnalysisReport.getRecordTimeEnd().getTime()) : null;
stmt = conn.prepareStatement(sql1.toString());
stmt.setDate(1, startTime);
stmt.setDate(2, endTime);
if (isNewYear) {
stmt.setDate(3, startTime);
stmt.setDate(4, endTime);
}
// 设置每次取的数据
stmt.setFetchSize(1000);
ResultSet rs = stmt.executeQuery();
while(rs.next()){
Map<String, Object> item = new HashMap<String, Object>();
item.put("checkinId", rs.getString(1));
item.put("targetId", rs.getString(2));
item.put("name", rs.getString(3));
item.put("unit", rs.getString(4));
item.put("results", rs.getString(5));
item.put("targetPro",rs.getString(6));
item.put("spTargetContrast",rs.getString(7));
mapList.add(item);
}
jdbcUtil.free(rs, stmt, conn);
} catch (SQLException e) {
logger.error(String.format("执行sql查询异常:%s", e.getMessage()));
// 抛出异常 ,让上级事务回滚
throw new RuntimeException(e);
}
这里设置了fetchSize后执行速度明显快了很多,具体设置多大得看实际上服务器的配置了。
如果是使用的mybatis,设置fetchSize更方便,如下:
实例代码
<select id="getLyRegisterList" fetchSize="1000" resultType="DynaBean">
数据库都是使用的Oracle