Как предотвратить вставку повторяющихся строк?

Прошу прощения за неконкретный вопрос, но я не знаю, как выразить это в одном предложении. Вот почему я даже не мог попытаться найти это в Google.

У меня есть ресурс DropWizard, и я использовал Hibernate для доступа к своей БД. У меня есть следующие объекты с их атрибутами.

Trip
====
id
from_place
to_place
time
user_who_booked_it
trip_group_ref

TripGroup
=========
id
from_place
to_place
time

TripGroup в основном группирует все поездки, которые имеют одинаковые места и время. Позже это пригодится в некоторых других задачах.

Ресурс, который создает объект Trip, сначала должен проверить, существует ли соответствующий объект TripGroup, и если нет, то он создает его. Это создает проблему. При наличии одновременных запросов возможно создание двух или более TripGroup экземпляров с точно такими же параметрами.

Как мне это решить?

Одним из возможных решений может быть то, что я оберну часть кода, которая проверяет и создает эти объекты, внутри блока synchronized. Однако, возможно, это не сработает, поскольку фиксация будет запущена после завершения метода ресурса, то есть за пределами блока synchronized.


person AppleGrew    schedule 25.03.2015    source источник


Ответы (1)


Ограничения дублирования действительно должны быть установлены на уровне базы данных. Даже если вы можете справиться со всеми проблемами параллелизма в коде своего приложения, ничто не мешает клиенту БД вставить дубликат строки TripGroup непосредственно в вашу таблицу.

В Dropwizard, если вы используете Hibernate, вы можете аннотировать свой класс модели TripGroup примерно так:

@Entity
@Table(name = "trip_group", uniqueConstraints = @UniqueConstraint(columnNames = {"id", "fromPlace", "toPlace", "time"}))
public class TripGroup

Это создаст ограничение в вашей БД, и вы получите сообщение об ошибке, когда оно будет нарушено. Если вы используете JDBI, вам нужно вручную создать таблицу или использовать Liquibase.

person yunspace    schedule 25.03.2015
comment
Есть проблема. Да, это предотвратит проблему, однако пользователь получит ошибку 500. Как поймать и повторить? - person AppleGrew; 26.03.2015
comment
Если у вас есть дубликат, который является нарушением ограничения, нет смысла повторять попытку с теми же параметрами. Не уверен, что понял ваш вариант использования. - person yunspace; 26.03.2015
comment
Когда возникает ошибка нарушения ограничения, DropWizard регистрирует это и отправляет клиенту ошибку 500. Мой вопрос: возможно ли, что DropWizard вместо того, чтобы повторить эту попытку еще раз, снова вызовет тот же ресурс с теми же параметрами? - person AppleGrew; 26.03.2015
comment
Лучший способ справиться с этим — перехватить исключение и ответить статусом 422, потому что сущность с этим уникальным полем уже существует. - person th3morg; 26.03.2015