Условие гонки в Postgres SQL с использованием Spring data JpaRepository

#spring #spring-data-jpa #spring-data

#spring #spring-data-jpa #spring-данные

Вопрос:

Я сталкиваюсь со странной проблемой в моей реализации, когда я сохраняю данные в базе данных PostgresSQL с использованием хранилища Spring data JpaRepository

В моем классе сущностей у меня есть следующие столбцы:

     @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    private int id;
    
    @Column(name = "field1", nullable = false, length = 16)
    private String field1;

    @Column(name = "field2", nullable = false, length = 16)
    private String field2;

    @Column(name = "field3", nullable = false, length = 16)
    private String field3;
  

Изначально я избегал объявления полей выше как составных, поскольку было много полей, с которыми нужно было обращаться как с составными ключами. Я думал, что проверка кода Java поможет во всех сценариях

Итак, в принципе, я должен поддерживать уникальность каждой строки на основе field1, field2 и field3. Это было основным требованием, для которого у меня были проверки в моем Java-коде, что, если в базе данных существует какая-либо запись для комбинации полей 1, 2 и 3, я использовал исключения Java

Эти значения не могут повторяться в двух строках. Все было хорошо, пока приложение не было протестировано в некоторых ошибочных бизнес-сценариях, которые никогда бы не произошли на производстве, но были запущены по ошибке

Что происходит сейчас, так это то, что если 2 запроса запускаются в одном и том же экземпляре с точно такими же 3 полями выше (через скрипт), то они оба попадают в базу данных, поскольку оба получают проверку ввода как false

Разрешит ли ситуацию объявление их всех как одного составного ключа?

Комментарии:

1. Вы можете начать с добавления уникального ограничения в postgres для обеспечения безопасности

Ответ №1:

Вы должны определить уникальное ограничение в вашей базе данных в дополнение к ограничению JPA.

 @Entity
@Table(uniqueConstraints={
    @UniqueConstraint(columnNames = {"field1", "field2", "field3"})
}) 
public class MyEntity {
  ...
}
  

Комментарии:

1. Конечно. Я попробую это и вернусь. Спасибо за вашу помощь

2. Я попробовал предложение выше, и оно работает в случае моих интеграционных тестов, где я создаю H2 в базе данных памяти, которая использует определения сущностей для создания таблиц на протяжении всего срока службы интеграционных тестов. Однако после развертывания во время выполнения uniqueconstraint не работает в реальных таблицах. Я предполагаю, что мне также нужно изменить скрипт liquibase, который я использую для создания реальных таблиц. Только добавление вышеуказанного к классам Java @Entity не сработает. Пожалуйста, поправьте меня, если я ошибаюсь