Databases 5 min read

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.

Java Architect Essentials
Java Architect Essentials
Java Architect Essentials
Implementing Streaming Reads with MyBatis and JDBC for Large Report Exports

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

databaseStreamingMyBatisJDBCResultHandler
Java Architect Essentials
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.