1.为什么使用流式查询?
普通查询方式:
1)JVM进程内数据库线程池,某一线程执行查询时,调用mysql驱动程序。
2)mysql驱动向mysql服务器发起TCP请求,服务器端根据条件查询匹配的数据,然后通过TCP链接发送到MySQL驱动。
3)mysql驱动把符合条件的数据缓存到驱动内存中,待数据发送结束,返回给应用程序缓存数据。
所以,mysql驱动内存就可能在访问大量数据(使用场景)时发生OOM。
2.JDBC编程中mysql流式查询
为了有效避免OOM,mysql客户端流式查询不会同时把服务器端的所有符合条件的数据缓存起来,而是一部分一部分的把服务器端返回的数据返回给应用程序层。
代码示例:
public void selectData(String sqlCmd,) throws SQLException {
validate(sqlCmd);
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = petadataSource.getConnection();
stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);
rs = stmt.executeQuery();
try {
while(rs.next()){
try {
System.out.println("one:" + rs.getString(1) + "two:" + rs.getString(2) + "thrid:" + rs.getString(3));
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} finally {
close(stmt, rs, conn);
}
}
3.Mybatis 中使用流式查询
①.MyBatisCursorItemReader
1)配置文件:注入MyBatisCursorItemReader
2)mapper文件配置:
3) 代码使用:
Map
param.put("oredCriteria", example.getOredCriteria());
// 设置参数
myMyBatisCursorItemReader.setParameterValues(param);
// 创建游标
myMyBatisCursorItemReader.open(new ExecutionContext());
//使用游标迭代获取每个记录
Long count = 0L;
Bean bean;
while ((bean = myMyBatisCursorItemReader.read()) != null) {
System.out.println(JSON.toJSONString(bean));
++count;
}
②.ResultHandler
1)配置mapper 的fetchSize属性
2)代码使用
SqlSession session = sqlSessionFactory.openSession();
session.select("selectByExample", example, new ResultHandler() {
@Override
public void handleResult(ResultContext resultContext) {
Bean bean = (Bean) resultContext.getResultObject();
System.out.println(resultContext.getResultCount());
System.out.println(JSON.toJSONString(bean));
}
});
PS:
参考:
1.转载自并发编程网 – ifeve.com 本文链接地址: MySQL中流式查询使用
2.https://www.jianshu.com/p/0339c6fe8b61