Поскольку нет конкретного примера или описания системы, я немного обобщу. Если вы предоставите конкретный пример, я могу добавить дополнительную информацию. Каждое решение имеет контекст , к которому оно относится лучше всего, и, конечно, всегда есть компромисс
Давайте зададим пару вопросов относительно характера этого кода и что он представляет
Кто отвечает за генерацию Code : Пользователь системы или System самой?
Может ли код быть абсолютно случайным (например, UUID)?
Код, сгенерированный по специальному алгоритму ( SSN или, возможно, CarPartNumber , который состоит из различных частей со специальным значением)
И еще один очень важный вопрос:
- Как часто мы ожидаем, что эти уникальные нарушения произойдут?
Если ответ на вопрос 2 Да, то у вас нет проблем. Вы можете иметь дубликаты UUID, но шансы очень малы. Вы можете на всякий случай добавить в свою БД Unique Constrant и рассматривать это нарушение как обычную ошибку, которая вас не волнует, поскольку она будет происходить раз в миллион лет.
Если ответ на вопрос 3 - «Да», то у нас другая ситуация. В многопользовательской системе вы не можете избежать параллелизма. Есть несколько способов разобраться с ситуацией:
Если вы решите использовать блокировку, вы можете заблокировать весь ресурс Foo или заблокировать только генерацию Code .
Вариант 1 :
Вам придется обработать исключение SQLE. Этот метод сегодня используется в большинстве приложений, поскольку он обеспечивает плавное взаимодействие с пользователем , не вызывая зависание приложения в течение длительного времени, поскольку кто-то заблокировал ресурс.
Вы можете использовать абстракцию, например, Репозиторий. Определите свое собственное исключение уровня приложения UniqueCodeViolationException, которое будет выброшено хранилищем. Репозиторий попытается {} перехватить {} SQLException, обработать его и обернуть его в UniqueCodeViolationException, когда он сравнивает коды ошибок. Это не спасет вас от проверки, но, по крайней мере, если вы скроете конкретные ошибки, и обработка будет выполняться только в одном месте.
Option2 :
Иногда вам действительно нужно убедиться, что нет параллелизма, поэтому вы используете эту опцию. В этом случае вам придется заблокировать процесс создания Foo только для одного пользователя и не позволить другим иметь возможность даже открыть диалоговое окно / форму / страницу для создания Foo , если есть блокировка.
Это обеспечивает согласованность и позволяет избежать проблемы путем создания системы, которая в основном непригодна для нескольких пользователей, ориентированных на один и тот же Foo . Вполне возможно, что в создаваемом приложении будет только один человек, ответственный за создание Foo , или может быть, что параллелизм очень низок, так что это может быть хорошим решением.
У меня есть друзья, которые используют эту блокировку в приложении для Страховки . Обычно в своем заявлении один человек собирается в один офис оформить страховку . таким образом, вероятность одновременного создания страховки для одного и того же человека очень мала, а стоимость нескольких страховок для одного и того же человека очень высока.
Вариант 3:
С другой стороны, если ваш код сгенерирован системой , вы можете иметь CodeGenerationService , который работает с генерациями кода и обеспечивает генерацию уникальных кодов.Вы можете иметь очередь с этими запросами.В каждой операции генерации в Сервисе вы можете проверить, существует ли этот код, и вернуть ошибку (или выбросить исключение).
Теперь на вопрос 4 .Если вы не ожидаете частых коллизий, просто добавьте Unique Constraint в вашу БД и воспринимайте это как общую неожиданную ошибку.Добавьте проверку, если Code уже существует, и покажите ошибку, если она есть.
У вас все еще может быть параллелизм, поэтому будет небольшое изменение, если один пользователь добавит Foo , а другой получит ошибку "Ой ... что-то не так ... пожалуйста, попробуйте еще раз".Так как это будет происходить раз в 100 лет, это нормально.
Последнее решение значительно упростит вашу систему, игнорируя особые ситуации, которые могут возникнуть в редких ситуациях.