diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/EntryPersistenceService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/EntryPersistenceService.java index 2732de9d7..52bd92b8d 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/EntryPersistenceService.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/EntryPersistenceService.java @@ -11,9 +11,12 @@ import com.iqser.red.service.persistence.management.v1.processor.service.persist import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.type.DictionaryEntryType; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; + +import org.springframework.dao.DataIntegrityViolationException; import org.springframework.stereotype.Service; import javax.transaction.Transactional; + import java.util.List; import java.util.stream.Collectors; @@ -34,34 +37,43 @@ public class EntryPersistenceService { switch (dictionaryEntryType) { case ENTRY: - var dictionaryEntries = entries.stream().map(word -> { + entries.stream().forEach(word -> { DictionaryEntryEntity entry = new DictionaryEntryEntity(); entry.setVersion(version); entry.setValue(word); entry.setType(type); - return entry; - }).collect(Collectors.toList()); - entryRepository.saveAll(dictionaryEntries); + try { + entryRepository.save(entry); + } catch (DataIntegrityViolationException e) { + entryRepository.undeleteEntryIfDeleted(typeId, entry.getValue(), version); + } + }); break; case FALSE_POSITIVE: - var dictionaryFalsePositiveEntries = entries.stream().map(word -> { + entries.stream().forEach(word -> { DictionaryFalsePositiveEntryEntity entry = new DictionaryFalsePositiveEntryEntity(); entry.setVersion(version); entry.setValue(word); entry.setType(type); - return entry; - }).collect(Collectors.toList()); - falsePositiveEntryRepository.saveAll(dictionaryFalsePositiveEntries); + try { + falsePositiveEntryRepository.save(entry); + } catch (DataIntegrityViolationException e) { + falsePositiveEntryRepository.undeleteEntryIfDeleted(typeId, entry.getValue(), version); + } + }); break; case FALSE_RECOMMENDATION: - var dictionaryFalseRecommendationsEntries = entries.stream().map(word -> { + entries.stream().forEach(word -> { DictionaryFalseRecommendationEntryEntity entry = new DictionaryFalseRecommendationEntryEntity(); entry.setVersion(version); entry.setValue(word); entry.setType(type); - return entry; - }).collect(Collectors.toList()); - falseRecommendationEntryRepository.saveAll(dictionaryFalseRecommendationsEntries); + try { + falseRecommendationEntryRepository.save(entry); + } catch (DataIntegrityViolationException e) { + falseRecommendationEntryRepository.undeleteEntryIfDeleted(typeId, entry.getValue(), version); + } + }); break; } } diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/EntryRepository.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/EntryRepository.java index 631f3b13b..820ca983a 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/EntryRepository.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/EntryRepository.java @@ -2,6 +2,8 @@ package com.iqser.red.service.persistence.management.v1.processor.service.persis import java.util.List; +import javax.transaction.Transactional; + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; @@ -26,4 +28,9 @@ public interface EntryRepository extends JpaRepository findByTypeIdAndVersionGreaterThan(String typeId, long version); + @Modifying + @Transactional + @Query("update DictionaryEntryEntity e set e.deleted = false, e.version = :version where e.type.id =:typeId and e.value = :value and e.deleted = true") + void undeleteEntryIfDeleted(String typeId, String value, long version); + } diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/FalsePositiveEntryRepository.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/FalsePositiveEntryRepository.java index a985fc44e..744537e83 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/FalsePositiveEntryRepository.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/FalsePositiveEntryRepository.java @@ -2,6 +2,8 @@ package com.iqser.red.service.persistence.management.v1.processor.service.persis import java.util.List; +import javax.transaction.Transactional; + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; @@ -27,4 +29,10 @@ public interface FalsePositiveEntryRepository extends JpaRepository findByTypeIdAndVersionGreaterThan(String typeId, long version); + + @Modifying + @Transactional + @Query("update DictionaryFalsePositiveEntryEntity e set e.deleted = false, e.version = :version where e.type.id =:typeId and e.value = :value and e.deleted = true") + void undeleteEntryIfDeleted(String typeId, String value, long version); + } diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/FalseRecommendationEntryRepository.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/FalseRecommendationEntryRepository.java index 28d8f3549..00b86ff1c 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/FalseRecommendationEntryRepository.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/FalseRecommendationEntryRepository.java @@ -2,6 +2,8 @@ package com.iqser.red.service.persistence.management.v1.processor.service.persis import java.util.List; +import javax.transaction.Transactional; + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; @@ -28,4 +30,10 @@ public interface FalseRecommendationEntryRepository extends JpaRepository findByTypeIdAndVersionGreaterThan(String typeId, long version); + + @Modifying + @Transactional + @Query("update DictionaryFalseRecommendationEntryEntity e set e.deleted = false, e.version = :version where e.type.id =:typeId and e.value = :value and e.deleted = true") + void undeleteEntryIfDeleted(String typeId, String value, long version); + } diff --git a/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/DictionaryController.java b/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/DictionaryController.java index 80e01df78..25247752a 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/DictionaryController.java +++ b/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/DictionaryController.java @@ -79,14 +79,13 @@ public class DictionaryController implements DictionaryResource { var currentVersion = getCurrentVersion(typeResult); - List existing = entryPersistenceService.getEntries(typeId, dictionaryEntryType, null) + if (removeCurrent) { + List existing = entryPersistenceService.getEntries(typeId, dictionaryEntryType, null) .stream() .filter(e -> !e.isDeleted()) .map(BaseDictionaryEntry::getValue) .collect(toList()); - if (removeCurrent) { - List removed = new ArrayList<>(existing); removed.removeAll(cleanEntries); @@ -97,13 +96,7 @@ public class DictionaryController implements DictionaryResource { entryPersistenceService.addEntry(typeId, added, currentVersion + 1, dictionaryEntryType); } else { - - List added = new ArrayList<>(cleanEntries); - added.removeAll(existing); - if (added.isEmpty()) { - return; - } - entryPersistenceService.addEntry(typeId, added, currentVersion + 1, dictionaryEntryType); + entryPersistenceService.addEntry(typeId, new ArrayList<>(cleanEntries), currentVersion + 1, dictionaryEntryType); } dictionaryPersistenceService.incrementVersion(typeId); diff --git a/persistence-service-v1/persistence-service-server-v1/src/main/resources/db/changelog/24-add-unique-constraint-for-dictionary.yaml b/persistence-service-v1/persistence-service-server-v1/src/main/resources/db/changelog/24-add-unique-constraint-for-dictionary.yaml new file mode 100644 index 000000000..1a2bc5460 --- /dev/null +++ b/persistence-service-v1/persistence-service-server-v1/src/main/resources/db/changelog/24-add-unique-constraint-for-dictionary.yaml @@ -0,0 +1,17 @@ +databaseChangeLog: + - changeSet: + id: add-unique-constraint-for-dictionary + author: ali + changes: + - addUniqueConstraint: + columnNames: value, type_id + constraintName: unique_constraint_dictionary_false_recommendation_entry + tableName: dictionary_false_recommendation_entry + - addUniqueConstraint: + columnNames: value, type_id + constraintName: unique_constraint_dictionary_entry + tableName: dictionary_entry + - addUniqueConstraint: + columnNames: value, type_id + constraintName: unique_constraint_dictionary_false_positive_entry + tableName: dictionary_false_positive_entry diff --git a/persistence-service-v1/persistence-service-server-v1/src/main/resources/db/changelog/db.changelog-master.yaml b/persistence-service-v1/persistence-service-server-v1/src/main/resources/db/changelog/db.changelog-master.yaml index 16685cf18..425c6b55e 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/persistence-service-v1/persistence-service-server-v1/src/main/resources/db/changelog/db.changelog-master.yaml @@ -55,3 +55,5 @@ databaseChangeLog: file: db/changelog/22-add-soft-delete-time-to-entity.changelog.yaml - include: file: db/changelog/23-quartz.changelog.yaml + - include: + file: db/changelog/24-add-unique-constraint-for-dictionary.yaml \ No newline at end of file diff --git a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/performance/FilePerformanceTest.java b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/performance/FilePerformanceTest.java index 4ae715b8f..26c889221 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/performance/FilePerformanceTest.java +++ b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/performance/FilePerformanceTest.java @@ -17,6 +17,7 @@ import org.assertj.core.util.Sets; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; import java.time.OffsetDateTime; import java.util.*; @@ -105,8 +106,13 @@ public class FilePerformanceTest extends AbstractPersistenceServerServiceTest { de.setValue("Dictionary Entry" + i); des.add(de); + try { + entryRepository.save(de); + } catch (DataIntegrityViolationException e) { + log.info("Duplicate Type: {}", te.getType()); + entryRepository.undeleteEntryIfDeleted(te.getId(), de.getValue(), de.getVersion()); + } } - entryRepository.saveAll(des); log.info("Created Type: {}", te.getType()); }