一、流式查询与正常查询区别
正常查询
将数据依据条件全部查询到内存中,可能会导致oom问题
流式查询
流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果
二、应用场景
当查询结果过大,或者需要对查询结果进行复杂的转换时可以使用流式查询,如:写文件、excel等
三、例子
通过ResultHandler
mapper
List<Users> selectList(ResultHandler resultHandler);
mapper.xml
<select id="selectList" parameterType="java.lang.Long" resultMap="BaseResultMap" resultSetType="FORWARD_ONLY" fetchSize="-2147483648">
select
<include refid="Base_Column_List" />
from users
</select>
service
List<Users> usersList = new ArrayList<>();
usersList = usersMapper.selectList(new ResultHandler() {
@Override
public void handleResult(ResultContext resultContext) {
// 一条一条数据进行查询
System.out.println(resultContext);
}
});
return usersList;
通过流式API
mapper
Cursor<Users> selectAll();
mapper.xml
<select id="selectAll" resultType="com.example.bootdemo.domain.Users" resultSetType="FORWARD_ONLY" fetchSize="-2147483648">
select
<include refid="Base_Column_List" />
from users
</select>
service
List<Users> usersList = new ArrayList<>();
switch (value) {
case "1":
// 通过SqlSessionFactory
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
UsersMapper mapper = sqlSession.getMapper(UsersMapper.class);
Cursor<Users> users = mapper.selectAll();
users.forEach(item -> {
usersList.add(item);
});
} catch (SqlSessionException e) {
e.printStackTrace();
}
break;
case "2":
// 通过TransactionTemplate,开启事务
TransactionDefinition transactionDefinition = new DefaultTransactionDefinition(TransactionDefinition.ISOLATION_DEFAULT);
TransactionStatus status = transactionManager.getTransaction(transactionDefinition);
Cursor<Users> users = usersMapper.selectAll();
users.forEach(item -> {
usersList.add(item);
});
transactionManager.commit(status);
break;
default:
break;
}
return usersList;
四、流式查询注意
MySQL 流式查询的坑
当通过流式查询获取一个ResultSet后,在你通过next迭代出所有元素之前或者调用close关闭它之前,你不能使用同一个数据库连接去发起另外一个查询,否者抛出异常(第一次调用的正常,第二次的抛出异常)。