From 835dc773820c1349b1bfaa8e40415ef25fc104d3 Mon Sep 17 00:00:00 2001 From: Marcel Date: Wed, 29 Apr 2026 18:27:18 +0200 Subject: [PATCH] fix(transcription): persist mentionedPersons on block update; eager-load collection TranscriptionService.updateBlock was not writing mentionedPersons from the DTO back to the entity, so @mentions were lost on every save. Clear-then-addAll pattern avoids Hibernate orphan issues with @ElementCollection. Switch @ElementCollection fetch to EAGER so callers can read mentionedPersons outside an active transaction without a LazyInitializationException. Co-Authored-By: Claude Sonnet 4.6 --- .../model/TranscriptionBlock.java | 2 +- .../service/TranscriptionService.java | 2 ++ .../service/TranscriptionServiceTest.java | 26 +++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/org/raddatz/familienarchiv/model/TranscriptionBlock.java b/backend/src/main/java/org/raddatz/familienarchiv/model/TranscriptionBlock.java index 3ff9ca78..af56efe4 100644 --- a/backend/src/main/java/org/raddatz/familienarchiv/model/TranscriptionBlock.java +++ b/backend/src/main/java/org/raddatz/familienarchiv/model/TranscriptionBlock.java @@ -35,7 +35,7 @@ public class TranscriptionBlock { @Column(columnDefinition = "TEXT") private String text; - @ElementCollection(fetch = FetchType.LAZY) + @ElementCollection(fetch = FetchType.EAGER) @CollectionTable( name = "transcription_block_mentioned_persons", joinColumns = @JoinColumn(name = "block_id")) diff --git a/backend/src/main/java/org/raddatz/familienarchiv/service/TranscriptionService.java b/backend/src/main/java/org/raddatz/familienarchiv/service/TranscriptionService.java index 589e7f56..b96f1a2a 100644 --- a/backend/src/main/java/org/raddatz/familienarchiv/service/TranscriptionService.java +++ b/backend/src/main/java/org/raddatz/familienarchiv/service/TranscriptionService.java @@ -134,6 +134,8 @@ public class TranscriptionService { if (dto.getLabel() != null) { block.setLabel(dto.getLabel()); } + block.getMentionedPersons().clear(); + block.getMentionedPersons().addAll(dto.getMentionedPersons()); block.setUpdatedBy(userId); TranscriptionBlock saved = blockRepository.save(block); diff --git a/backend/src/test/java/org/raddatz/familienarchiv/service/TranscriptionServiceTest.java b/backend/src/test/java/org/raddatz/familienarchiv/service/TranscriptionServiceTest.java index 8aa6ee99..bb264048 100644 --- a/backend/src/test/java/org/raddatz/familienarchiv/service/TranscriptionServiceTest.java +++ b/backend/src/test/java/org/raddatz/familienarchiv/service/TranscriptionServiceTest.java @@ -17,6 +17,7 @@ import org.raddatz.familienarchiv.model.BlockSource; import org.raddatz.familienarchiv.model.Document; import org.raddatz.familienarchiv.model.DocumentAnnotation; import org.raddatz.familienarchiv.model.Person; +import org.raddatz.familienarchiv.model.PersonMention; import org.raddatz.familienarchiv.model.ScriptType; import org.raddatz.familienarchiv.model.TranscriptionBlock; import org.raddatz.familienarchiv.model.TranscriptionBlockVersion; @@ -215,6 +216,31 @@ class TranscriptionServiceTest { assertThat(result.getSource()).isEqualTo(BlockSource.MANUAL); } + @Test + void updateBlock_replacesMentionedPersonsFromDto() { + UUID docId = UUID.randomUUID(); + UUID blockId = UUID.randomUUID(); + UUID personId = UUID.randomUUID(); + + TranscriptionBlock block = TranscriptionBlock.builder() + .id(blockId).documentId(docId).text("old").build(); + when(blockRepository.findByIdAndDocumentId(blockId, docId)).thenReturn(Optional.of(block)); + when(blockRepository.save(any())).thenAnswer(inv -> inv.getArgument(0)); + when(documentService.getDocumentById(any())).thenReturn( + Document.builder().scriptType(ScriptType.TYPEWRITER).build()); + + PersonMention mention = new PersonMention(personId, "Auguste"); + UpdateTranscriptionBlockDTO dto = UpdateTranscriptionBlockDTO.builder() + .text("@Auguste text") + .mentionedPersons(List.of(mention)) + .build(); + + TranscriptionBlock result = transcriptionService.updateBlock(docId, blockId, dto, UUID.randomUUID()); + + assertThat(result.getMentionedPersons()) + .containsExactly(mention); + } + @Test void updateBlock_triggersTraining_whenKurrentSenderPresent() { UUID docId = UUID.randomUUID();