最近公司提了个需求,说公司的旧系统的报表导出的时候,数据量超过一万就导不出来了。经过分析,是旧系统做了限制。在更新的时候,查看了导出时虚拟机GC情况,发现原先程序执行时,内存激增,经过Google决定采用流式读取对sql进行优化。
JDBC三种读取方式:一次全部(默认):一次获取全部。流式:多次获取,一次一行。游标:多次获取,一次多行。mybatis默认采取第一种。
开发环境:jdk1.8、intellijIDEA
mybatis3、springMVC、Spring4
实现步骤:实现流式读取的方式不止一种,但是我只能说我解决的这种,对不起,我不是大神级的。
这里采用的controller、service、dao分层开发
在service层调用dao接口是,增加一个回调参数ResultHandler。对应的dao接口返回值为voidmapper填写parameterType、resultMap、resultSetType=“FORWARD_ONLY”、fetchSize="-"为什么dao返回值为void还要在mapper写resultMap?因为回调要用你的resultMap处理,但是不应该返回给service,因为回调处理好了
示例代码controller层:
RequestMapping("/export")publicvoidexport(Vovo,Stringprops,HttpServletResponseresponse){//.......list=ossVipCustomService.selectForwardOnly(vo,Order.build());//......}service层:(重点)
publicListBoselectForwardOnly(Vovo,Orderorder){finalListBolist=newArrayList();mapper.selectForwardOnly(vo,order,newResultHandlerBo(){
OverridepublicvoidhandleResult(ResultContext?extendsBoresultContext){/**回调处理逻辑*/list.add(resultContext.getResultObject());}});returnlist;}dao层:(重点)
/***流式读取数据*
paramvo查询对象*paramorder排序*paramossVipCustomerBoResultHandler回调处理*/voidselectForwardOnly(Param("record")Vovo,Param("order")Orderorder,ResultHandlerBohandler);mapper:(重点)
selectid="selectForwardOnly"parameterType="