ARTICLE AD BOX
I am developing a Spring Boot 3 application (Java 25) that periodically checks for updates from external APIs (GitHub/StackOverflow). I have two repository implementations: one using JdbcTemplate (SQL) and another using EntityManager (JPA/ORM).
The application uses a fixed thread pool to process links in parallel.
The Problem: When I use the SQL implementation, everything works perfectly. However, when I switch to the JPA implementation, I consistently get the following error during parallel execution:
A problem occurred in the SQL executor : Error advancing (next) ResultSet position [This ResultSet is closed.]
My JPA Repository method:
@Override public OffsetDateTime getUpdatedAtByUrl(String url) { String query = "select l.lastUpdatedAt from Link l where l.url = :url"; return entityManager .createQuery(query, OffsetDateTime.class) .setParameter("url", url) .getResultStream() .findFirst() .orElse(null); }My Service logic:
ExecutorService executor = Executors.newFixedThreadPool(threadCount); for (LinkResponse link : links) { executor.submit(() -> processLink(link)); // Calls the repository inside }If I replace .getResultStream().findFirst() with .getResultList().stream().findFirst(), the error disappears.
My questions are:
Why does getResultStream() keep the ResultSet open in a way that causes conflicts in a multi-threaded environment, even if the threads are supposedly independent?
Is it a known limitation of Hibernate's Stream support when combined with Spring's transaction management and ExecutorService?
What is the recommended way to fetch a single optional value in JPA to avoid this "ResultSet is closed" race condition?
