Хобрук: Ваш путь к мастерству в программировании

Предотвращение нарушения ограничения UNIQUE с помощью Hibernate

У меня есть таблица типа (id INTEGER, sometext VARCHAR(255), ....) с id в качестве первичного ключа и ограничением UNIQUE на sometext. Он используется на веб-сервере, где запрос должен найти id, соответствующий заданному sometext, если он существует, иначе вставляется новая строка.

Это единственная операция над этой таблицей. В этой таблице нет обновлений и других операций. Его единственной целью является постоянное количество встречающихся значений sometext. Это означает, что я не могу отказаться от id и использовать sometext в качестве ПК.

Я делаю следующее:

  • Во-первых, я обращаюсь к своему собственному кешу, чтобы избежать доступа к БД. Почти всегда это работает, и я закончил.
  • В противном случае я использую Hibernate Criteria, чтобы найти строку по sometext. Обычно это работает, и снова я закончил.
  • В противном случае мне нужно вставить новую строку.

Это работает нормально, за исключением случаев, когда есть два перекрывающихся запроса с одним и тем же sometext. Затем выдается ConstraintViolationException. Мне нужно что-то вроде INSERT IGNORE или INSERT ... ON DUPLICATE KEY UPDATE (синтаксис Mysql) или MERGE (Firebird синтаксис).

Интересно, какие есть варианты?

AFAIK Hibernate merge работает только на ПК, так что это неуместно. Я предполагаю, что собственный запрос может помочь или нет, так как он может быть зафиксирован или не зафиксирован, когда происходит второй INSERT.


  • Я не понимаю, почему вы не можете использовать какой-то текст в качестве ПК. 09.05.2016
  • Кроме того, почему вы не можете просто поймать ConstraintViolationException (и проигнорировать его)? 09.05.2016
  • @Thilo 1. Потому что мне нужно число вместо текста. Вот почему я использую id. Возможно, я мог бы использовать sometext и сохранить число в другом столбце (я мог бы гарантировать уникальность каким-то другим способом). +++ 2. Мог бы, если бы знал, что это не вызвано чем-то другим. Но имя таблицы недоступно в исключении. Более того, это происходит в SessionImpl.flush (а не в INSERT), что, скорее всего, означает, что ничего не сохраняется. 09.05.2016
  • Re:2 Так вы делаете другие вещи в той же транзакции? Это необходимо? 09.05.2016
  • @Thilo Конечно, на самом деле важны другие вещи, а эта нумерация - нет. Я использую одну транзакцию для каждого веб-запроса, возможно, я мог бы использовать для этого другую. И, может быть, я мог бы сделать просто сброс и повторную попытку при ошибке (эта нумерация всегда происходит до реальной работы). 09.05.2016
  • Или просто запустите нумерацию под @Transactional(propagation = Propagation.REQUIRES_NEW), чтобы она выполнялась в отдельной транзакции. 09.05.2016
  • @Thilo Я не использую JPA и Spring, но идея у меня есть. Конечно, я могу это сделать. 09.05.2016

Ответы:


1

Просто позвольте базе данных обрабатывать параллелизм. Запустите вторичную транзакцию исключительно для вставки новой строки. если это не удается с ConstraintViolationException, просто откатите эту транзакцию и прочитайте новую строку.

09.05.2016

2

Не уверен, что это хорошо масштабируется, если вероятность дублирования высока, много дополнительной работы, если какой-то процент (зависит от базы данных) транзакций должен не выполнить вставку, а затем повторно выбрать.

Вторичная транзакция сводит к минимуму время, необходимое транзакции для добавления нового текста, при условии, что база данных поддерживает ее правильно, транзакция потока 1 может привести к зависанию выбора/вставки потока 2 до тех пор, пока транзакция потока 1 не будет зафиксирована. или откатился. Общий дизайн базы данных также может повлиять на пропускную способность транзакций.

Я не обязательно задаюсь вопросом, почему какой-то текст не может быть ПК, задаваясь вопросом, почему вам вообще нужно его разбивать. Конечно, большие тома могут существенно сэкономить место, если некоторые текстовые записи большие, почти похоже, что вы пытаетесь эмулировать индекс lucene, чтобы получить полный список текстовых значений.

09.05.2016
  • Я не беспокоюсь о производительности здесь, так как почти все покрывается кешем, и дубликаты будут очень редки. К вашему сведению, я нумерую адреса узлов запроса. Они довольно короткие, поэтому мне не нужно экономить место, но я также хочу сохранить их список в БД. Дублирование происходит только при наличии двух одновременных запросов от нового клиента (или двух клиентов с общим IP-адресом), что, вероятно, никогда не произойдет, кроме как при тестировании. 12.05.2016
  • Новые материалы

    Аргументы прогрессивного улучшения почти всегда упускают суть
    В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

    Введение в Джанго Фреймворк
    Схема «работать умно, а не усердно» В этой и последующих статьях я познакомлю вас с тем, что такое фреймворк Django и как создать свое первое приложение с помощью простых и понятных шагов, а..

    Настольный ПК как «одно кольцо, чтобы править всеми» домашних компьютеров
    Вид после 9 месяцев использования С настольных компьютеров все началось, но в какой-то момент они стали «серверами», и мы все перешли на ноутбуки. В прошлом году я столкнулся с идеей настольных..

    Расширенные методы безопасности для VueJS: реализация аутентификации без пароля
    Руководство, которое поможет вам создавать безопасные приложения в долгосрочной перспективе Безопасность приложений часто упускается из виду в процессе разработки, потому что основная..

    стройный-i18следующий
    Представляем стройную оболочку для i18next. Эта библиотека, основанная на i18next, заключает экземпляр i18next в хранилище svelte и отслеживает события i18next, такие как languageChanged,..

    Обзор 20 основных и современных методов работы с массивами в JavaScript
    Вы знаете их всех? В этом коротком посте я покажу сводку методов, доступных в JavaScript для работы с массивами. Я надеюсь, что вы найдете это полезным! В конце поста вы найдете ссылку на..

    Да, но я чувствую необходимость указать, что это или не единственные два.
    Да, но я чувствую необходимость указать, что это или не единственные два. Обучение с подкреплением (в качестве примера) также является важным.