Implementing Streaming Reads with MyBatis and JDBC for Large Report Exports
This article explains how to overcome export failures for reports exceeding ten thousand rows by using MyBatis streaming reads with JDBC, detailing the three read modes, required MyBatis configurations, and providing complete controller, service, DAO, and mapper code examples.
When a company's legacy system failed to export reports larger than ten thousand rows, the root cause was identified as the default JDBC fetch mode that loads the entire result set into memory, causing excessive GC pressure.
The solution is to switch to a streaming read mode, which retrieves rows incrementally, reducing memory consumption. MyBatis supports three read modes:
Full fetch (default): loads all rows at once.
Streaming: fetches one row at a time.
Cursor: fetches multiple rows per round.
Implementation uses a layered architecture (controller → service → DAO) and introduces a ResultHandler callback in the service layer. The DAO method returns void, while the mapper is configured with resultSetType="FORWARD_ONLY" and fetchSize="-2147483648" to enable forward‑only streaming.
Controller example:
@RequestMapping("/export")
public void export(Vo vo, String props, HttpServletResponse response) {
// ...
List<Bo> list = ossVipCustomService.selectForwardOnly(vo, Order.build());
// ...
}Service example (key part):
public List<Bo> selectForwardOnly(Vo vo, Order order) {
final List<Bo> list = new ArrayList<>();
mapper.selectForwardOnly(vo, order, new ResultHandler<Bo>() {
@Override
public void handleResult(ResultContext<? extends Bo> resultContext) {
// callback processing logic
list.add(resultContext.getResultObject());
}
});
return list;
}DAO interface (key part):
void selectForwardOnly(@Param("record") Vo vo,
@Param("order") Order order,
ResultHandler<Bo> handler);Mapper XML configuration (key part):
<select id="selectForwardOnly"
parameterType="com.*.Vo"
resultMap="GetListBo"
resultSetType="FORWARD_ONLY"
fetchSize="-2147483648">
SELECT * FROM customer
</select>With these changes, the application can export large datasets without running out of memory, demonstrating a practical use of JDBC streaming reads in a Spring‑MyBatis backend.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Architect Essentials
Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
