Play 1 и Hibernate 3.6: потоки пытаются создать одну и ту же запись одновременно. Как решить? - PullRequest
0 голосов
/ 15 марта 2020

Фон

Отказ от ответственности: Я своего рода спящий нуб. Я достаточно разбираюсь в этом, чтобы поддерживать программное обеспечение и вносить некоторые изменения, но не во все тонкости hibernate.

В инфраструктуре play есть интересная особенность, которую каждый https-запрос преобразует в одну транзакцию гибернации. Обычно это круто. Иногда приходит много запросов, которые пытаются вставить один и тот же набор данных, а также выполнять другие действия. Этого действительно нельзя избежать. Это, конечно, приводит к исключению. Естественно, я пытаюсь предотвратить это, спрашивая hibernate, присутствует ли этот набор данных до его вставки, но из-за характера параллелизма эта проверка не мешает другому потоку попытаться вставить данные спустя 3 миллисекунды.

Это также не представляет большой проблемы, если бы не одна транзакция для каждого запроса, на котором работает Play.
Когда hibernate неизбежно выдает ошибку из-за вышеизложенного, вся транзакция должна быть отброшена. Это включает в себя вещи, которые я хочу сохранить. Если бы не это, я просто создал бы отдельную транзакцию и использовал бы эту для вставки данных. Но я не могу, потому что вся моя кодовая база работает в предположении об одной транзакции. Тем не менее, теоретически я мог бы просто закрыть текущую транзакцию и создать новую, но тогда все присоединенные модели были бы отсоединены, и мне нужно было бы найти способ, чтобы сначала выяснить, какие модели были присоединены к старой транзакции, а затем повторно присоединить их. Это имеет свои проблемы. Код проблемного c находится в классе обслуживания, предназначенном для вставки данных такого типа в базу данных. Он понятия не имеет ни о чем другом. Это включает в себя, откуда это называется или в каком контексте. Он не может знать, какие модели подключены в транзакции ... (кроме как, если есть какой-то способ, которым hibernate мог бы сказать мне?) В конце концов, мне все равно, какой поток вставляет данные. Меня интересует только то, что он вообще вставлен. К сожалению, я не могу найти способ обойти эту проблему.

Текущее (безобразное) решение

То, что я сейчас делаю в качестве меры для устранения пробела, заключается в предотвращении параллелизма с использованием очереди. Это, конечно, сильно влияет на производительность, но лучше, чем ничего.

Вопрос

Так что, может быть, есть хитрый способ, который я не знаю, чтобы сказать hibernate, чтобы не бросать при обнаружении дубликата в этой очень конкретной c позиции в моем код?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...