java / intermediate
Snippet
Preventing Out-of-Memory Errors via JPA Query Result Streaming
Fetching large datasets as a single `List<T>` loads all records simultaneously into the JVM heap, risking `OutOfMemoryError`. Using Java 8 `Stream<T>` query return types alongside `@Transactional(readOnly = true)` allows the database cursor to stream rows incrementally, keeping heap consumption constant while processing extensive result sets.
snippet.java
java
1
2
3
4
5
6
7
8
9
10
@Servicepublic class ExportService {@Transactional(readOnly = true)public void exportAuditLogs(Consumer<AuditLog> consumer) {try (Stream<AuditLog> logStream = auditLogRepository.streamAllByStatus(Status.PENDING)) {logStream.forEach(consumer);}}}
spring
Breakdown
1
@Transactional(readOnly = true)
Maintains the underlying database connection and cursor open throughout the stream iteration.
2
try (Stream<AuditLog> logStream = auditLogRepository.streamAllByStatus(Status.PENDING)) {
Opens a try-with-resources block to guarantee closing the database cursor once streaming completes.
3
logStream.forEach(consumer);
Processes entities sequentially as they are fetched from the cursor without buffering all entries in memory.