Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Yes—but Java 8 streams process objects in your application; they do not issue SQL or automatically make a database fetch rows incrementally. Use JDBC or a repository framework to execute the query, then decide separately how rows are fetched and how Java transforms them. If a database-backed stream holds resources, close it.

What Java streams do—and what they do not do

A Stream<T> is a pipeline for processing elements from a source. Operations such as filter, sorted, and map can express query-like transformations, but the stream API does not translate those operations into SQL or contact the database. Oracle’s Java SE 8 tutorial describes combining stream operations to express rich data-processing queries in Part 2 of its Streams series.

That distinction matters: a Java-side filter runs on objects the application receives. A predicate in a SQL WHERE clause runs as part of the database query. Put conditions in SQL when they should determine which rows the database returns; use stream operations for transformations of the returned objects.

Query with JDBC, then process the rows

JDBC sends SQL through a Statement or PreparedStatement and exposes the result through a ResultSet. For values supplied by a user or other input, use a placeholder and bind the value rather than concatenating it into SQL. The pgJDBC query documentation demonstrates this pattern.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
List<Customer> customers = new ArrayList<>();

try (PreparedStatement statement = connection.prepareStatement(
        "SELECT id, name FROM customer WHERE active = ?")) {
    statement.setBoolean(1, true);

    try (ResultSet rs = statement.executeQuery()) {
        while (rs.next()) {
            customers.add(new Customer(
                    rs.getLong("id"),
                    rs.getString("name")));
        }
    }
}

List<String> names = customers.stream()
        .filter(customer -> customer.getName() != null)
        .map(Customer::getName)
        .collect(Collectors.toList());

Here the database applies WHERE active = ?. The Java pipeline then removes customers with a null name, maps the remaining objects to names, and collects those names into a list. This example materializes the customers before stream processing; it is not an incremental-fetch example.

Choose the row-fetch strategy separately

A stream-shaped API does not tell you how the driver retrieves rows. Fetching behavior depends on the driver and its configuration. These are distinct approaches:

Approach Where filtering and transformation happen Fetch behavior Resource guidance
SQL with an ordinary JDBC ResultSet loop SQL predicates run in the database; application code maps or processes returned rows. Driver-dependent. pgJDBC normally collects all query results at once. Close the result set and statement; manage the connection according to who owns it.
PostgreSQL JDBC cursor fetching SQL predicates run in the database; application code processes rows as batches arrive. pgJDBC can fetch batches when cursor conditions are met, with fetch size controlling the batch size. It may fall back to retrieving the full result in some cases. For pgJDBC cursor fetching, autocommit must be off and the statement must use a forward-only result set.
Spring Data query returning Stream<T> The repository and framework define the query; Java stream operations process the returned objects. Depends on the Spring Data module and store implementation. The return type alone does not establish cursor-based fetching. Close the stream and verify support and behavior for the exact module and version.
Materialize rows, then call collection.stream() The database executes SQL; Java operations run on the materialized objects. Rows are materialized before downstream stream processing in this approach. Memory use grows with the materialized result size; close JDBC resources according to their ownership and lifetime.

The PostgreSQL requirements above are specific to pgJDBC, not universal JDBC rules. See its documentation on issuing queries and processing results for cursor conditions and cases where cursor fetching cannot be used.

Use Spring Data streams with care

Spring Data JDBC 2.4.9 documents query methods that return Stream<T>, while warning that not all Spring Data modules support this return type and that a stream may wrap store-specific resources. Its versioned reference recommends closing such streams, for example with try-with-resources:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
try (Stream<User> users = repository.readAllByFirstnameNotNull()) {
    users.filter(user -> user.getLastname() != null)
         .forEach(this::process);
}

Check the documentation for the specific Spring Data module and version in your application. Do not infer incremental fetching merely from a repository method’s Stream<T> return type.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Close resource-backed streams

Most Java streams do not need closing, but the Java SE 8 API notes that streams backed by I/O resources may require it. A database-backed stream can retain resources underneath it, so use try-with-resources when the API returns a stream that you own. The Java SE 8 Stream API documentation also requires stream behavioral parameters to be non-interfering and usually stateless, and says a stream should be operated on only once.

If you build a custom stream over a ResultSet, that is application code—not a built-in JDBC feature. Its traversal logic must advance the result set, and its close handling must release the result set and statement, plus the connection if the wrapper owns it. Make ownership explicit so closing one component does not accidentally close a connection managed elsewhere.

Keep database work and stream work predictable

  • Use SQL for predicates that should limit which rows the database returns; use Java stream operations for application-side processing.
  • Choose row fetching based on the driver or framework’s documented behavior, not on the presence of Stream<T>.
  • Keep transaction boundaries and resource ownership clear when processing results.
  • Do not add .parallel() to a database-backed stream as a casual optimization. Safety and benefit depend on the driver, transaction, and repository implementation; benchmark concurrency changes in the target system.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.