From 56bcbcdd5cfbe5cb55868118f01f5e9795b6c527 Mon Sep 17 00:00:00 2001 From: Marcel Date: Mon, 18 May 2026 16:47:33 +0200 Subject: [PATCH] refactor(document): switch collections to LAZY + add @EntityGraph + @BatchSize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - receivers, tags, trainingLabels: FetchType.EAGER → FetchType.LAZY - sender: add explicit FetchType.LAZY (was implicitly lazy, now explicit) - @NamedEntityGraph("Document.full"): sender + receivers + tags - @NamedEntityGraph("Document.list"): sender + tags - DocumentRepository.findById overridden with @EntityGraph("Document.full") - DocumentRepository.findAll(Specification, Pageable) overridden with @EntityGraph("Document.list") - DocumentRepository.findAll(Specification) overridden with @EntityGraph("Document.list") for RECEIVER/SENDER sort paths - @BatchSize(50) on receivers and tags as fallback for any list path that does not go through an @EntityGraph method Fixes issue #467. Co-Authored-By: Claude Sonnet 4.6 --- .../familienarchiv/document/Document.java | 20 +++++++++++++++---- .../document/DocumentRepository.java | 12 +++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/org/raddatz/familienarchiv/document/Document.java b/backend/src/main/java/org/raddatz/familienarchiv/document/Document.java index 585bb788..7a6adba2 100644 --- a/backend/src/main/java/org/raddatz/familienarchiv/document/Document.java +++ b/backend/src/main/java/org/raddatz/familienarchiv/document/Document.java @@ -2,6 +2,7 @@ package org.raddatz.familienarchiv.document; import jakarta.persistence.*; import lombok.*; +import org.hibernate.annotations.BatchSize; import org.hibernate.annotations.CreationTimestamp; import org.hibernate.annotations.UpdateTimestamp; @@ -21,6 +22,15 @@ import java.util.HashSet; import java.util.Set; import java.util.UUID; +@NamedEntityGraph(name = "Document.full", attributeNodes = { + @NamedAttributeNode("sender"), + @NamedAttributeNode("receivers"), + @NamedAttributeNode("tags") +}) +@NamedEntityGraph(name = "Document.list", attributeNodes = { + @NamedAttributeNode("sender"), + @NamedAttributeNode("tags") +}) @Entity @Table(name = "documents") @Data // Lombok: Generiert Getter, Setter, ToString, etc. @@ -118,21 +128,23 @@ public class Document { @Builder.Default private ScriptType scriptType = ScriptType.UNKNOWN; - @ManyToMany(fetch = FetchType.EAGER) + @ManyToMany(fetch = FetchType.LAZY) @JoinTable(name = "document_receivers", joinColumns = @JoinColumn(name = "document_id"), inverseJoinColumns = @JoinColumn(name = "person_id")) + @BatchSize(size = 50) @Builder.Default private Set receivers = new HashSet<>(); - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "sender_id") private Person sender; - @ManyToMany(fetch = FetchType.EAGER) + @ManyToMany(fetch = FetchType.LAZY) @JoinTable(name = "document_tags", joinColumns = @JoinColumn(name = "document_id"), inverseJoinColumns = @JoinColumn(name = "tag_id")) + @BatchSize(size = 50) @Builder.Default private Set tags = new HashSet<>(); - @ElementCollection(fetch = FetchType.EAGER) + @ElementCollection(fetch = FetchType.LAZY) @CollectionTable(name = "document_training_labels", joinColumns = @JoinColumn(name = "document_id")) @Column(name = "label") @Enumerated(EnumType.STRING) diff --git a/backend/src/main/java/org/raddatz/familienarchiv/document/DocumentRepository.java b/backend/src/main/java/org/raddatz/familienarchiv/document/DocumentRepository.java index e907e5f2..35e2b1bb 100644 --- a/backend/src/main/java/org/raddatz/familienarchiv/document/DocumentRepository.java +++ b/backend/src/main/java/org/raddatz/familienarchiv/document/DocumentRepository.java @@ -7,6 +7,8 @@ import org.raddatz.familienarchiv.document.DocumentStatus; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Query; @@ -23,6 +25,16 @@ import java.util.UUID; @Repository public interface DocumentRepository extends JpaRepository, JpaSpecificationExecutor { + @EntityGraph("Document.full") + Optional findById(UUID id); + + @EntityGraph("Document.list") + Page findAll(Specification spec, Pageable pageable); + + @EntityGraph("Document.list") + List findAll(Specification spec); + + // Findet ein Dokument anhand des ursprünglichen Dateinamens // Wichtig für den Abgleich beim Excel-Import & Datei-Upload Optional findByOriginalFilename(String originalFilename);