java / expert
Snippet
Zustandsloses Ergebnis-Streaming mit JPA und Hibernate
Das Streaming großer Datensätze erfordert ein Fine-Tuning von Hibernate, um OutOfMemoryErrors zu verhindern. Durch Setzen der fetchSize und Aktivieren des readOnly-Modus zwingen wir den Treiber, Zeilen in Blöcken abzurufen und den Overhead des 1st-Level-Caches von Hibernate zu umgehen.
snippet.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Repositorypublic interface LargeDataRepository extends JpaRepository<Entity, Long> {@QueryHints(value = {@QueryHint(name = "org.hibernate.fetchSize", value = "500"),@QueryHint(name = "org.hibernate.readOnly", value = "true"),@QueryHint(name = "org.hibernate.cacheable", value = "false")})@Query("select e from Entity e")Stream<Entity> streamAllByCustomQuery();}// Usage in Service@Transactional(readOnly = true)public void processBatch() {try (Stream<Entity> entityStream = repository.streamAllByCustomQuery()) {entityStream.forEach(e -> { /* process and detach */ });}}
spring
Erklärung
1
Stream<Entity>
Rückgabetyp, der es ermöglicht, Ergebnisse einzeln zu verarbeiten, ohne die gesamte Liste in den RAM zu laden.
2
org.hibernate.fetchSize
Weist den JDBC-Treiber an, Ergebnisse in kleineren Blöcken statt alle auf einmal abzurufen.
3
try (Stream<Entity> ...)
KRITISCH: Der Stream muss innerhalb eines try-with-resources verwendet werden, um sicherzustellen, dass die zugrunde liegende Datenbankverbindung korrekt geschlossen wird.