powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Hibernate разрешение конфликтных ситуаций?
25 сообщений из 108, страница 1 из 5
Hibernate разрешение конфликтных ситуаций?
    #39174159
lor2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
допустим у меня есть код внутри транзакции:
бронирование помидоров на складе.
1) проверяем остатки помидоров на складе. если надо меньше помидоров чем остатки
то - бронируем и вычитаем из остатков. если больше - то отказ.
---конец---

теперь у меня допустим, на складе 20 помидоров. идет первая транзакция - бронируем 15 помидоров. вторая транзакция - бронируем 10 помидоров.

если они последовательно выполняются у нас получается что проходит первый бронькнул 15 остатки 5 второму - отказ.

если они идут одновременно: допустим, оба сделали проверку, оба получили тру. первый тяпнул 15 второй тяпнул 10 на выходе получаем минус 5???

как в данном случае пройдет конфликт? при условии что проверка и коммит внутри одной транзакции. мне сказали что там какой то момент с версионированием, проходит оптимистичная блокировка. но что то толком не нашел инфы об этом в инете. или ни у кого такого не возникает и хибер сам разводит всё?
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174180
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
lor2,
вам надо почитать про уровни изоляции транзакций. Вам скорее всего подойдет READ_COMMITTED
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174191
lor2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
забыл ник,

хорошо, значит получается в конфиге по умолчанию такой вариант произойти может да?
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174203
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
lor2забыл ник,

хорошо, значит получается в конфиге по умолчанию такой вариант произойти может да?

Я точно не помню, врядли READ_UNCOMMITED стоит по дефолту, скорее всего как раз READ_COMMITTED, если вы только сами не переопределили. Отвечая на ваш вопрос - хорошо что вы об этом задумываетесь, но хибер разрулит в вашем случае. в отличие от plain jdbc(правда и там можно выставить Connection autoCommit=false).

Хотя я тут подумал, смотря еще какой у вас код, можете показать sql?
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174208
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник

если они идут одновременно: допустим, оба сделали проверку, оба получили тру. первый тяпнул 15 второй тяпнул 10 на выходе получаем минус 5???

Что значит "тяпнул" ? Если заблокировать, то нет, не будет - т.к. второй не сможет заблокировать уже заблокированное. Будет exception
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174209
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нет, Hibernate ничего сам не разрулит.
При этом Hibernate это только инструмент, и прежде чем вы его начнете применять, хорошо бы понимать как он работает.
Поэтому для начала нужно понять две вещи
1) Теория заключается в том что надо выбрать между
- Пессимистической блокировкой, которая на уровне БД выглядит как SELECT FOR UPDATE. (Блокировка простая и надежная, но она выстраивает запросы в очередь и под высокой нагрузкой и при большой конкуренции начинаются сложности.) ... и оптимистичной блокировкой, которая достаточно просто реализована в хибере в виде @Version поля. Обе транзакции вычитывают свободные помидоры, обе пытаются их отнять от общего количества, но если это происходит одновременно, то одна из транзакций выхватывает исключения оптимистической блокировки. И уже вам как кодеру нужно решить что вы делаете с этим исключением.
Это решение хорошее, но нужно правильно продумывать обработку исключения.

2) Практика же иногда предлагает на много более простые решения, как например, SQL запрос выборки с одновременной валидацией значения.
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174219
lor2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
я нашел вот это:
setProperty("hibernate.connection.isolation", "2");

где уровень указвается. и да, что то читал насчет версионинга но в инете инфы как то маловато. значит люди с этим не сталкиваются. в практике же "посчитать количество помидор и отнять помидоры" это слишком коротакая транзакция и может действительно с этим по этой причине и не сталкиваются. скулем пользвоаться бы не хотелось по возможности. касательно аннотации @Version тоже не совсем ясно для меня как оно работает. я что ставлю эту аннотацию и проблема решена чтоль?

чуть ранее я задавал тут похожий вопрос - мне сказали - когда засовываешь всё в одну транзакцию то типа "так не будет" :)
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174228
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
lor2я нашел вот это:
setProperty("hibernate.connection.isolation", "2");

где уровень указвается. и да, что то читал насчет версионинга но в инете инфы как то маловато. значит люди с этим не сталкиваются. в практике же "посчитать количество помидор и отнять помидоры" это слишком коротакая транзакция и может действительно с этим по этой причине и не сталкиваются. скулем пользвоаться бы не хотелось по возможности. касательно аннотации @Version тоже не совсем ясно для меня как оно работает. я что ставлю эту аннотацию и проблема решена чтоль?

чуть ранее я задавал тут похожий вопрос - мне сказали - когда засовываешь всё в одну транзакцию то типа "так не будет" :)

Опять же, смотря что вы подразумеваете под посчитать помидоры и отнять. Как это реализовано?

В протейшем случае если есть таблица помидоры, и у нее есть поле количество а ваш код выглядит так:

Код: java
1.
2.
3.
4.
int count = select count of tomato
if (count > order.count) {
    update pomidors set count = count - order.count
}



и есть check constraint что поле count не может быть < 0, то достаточно выставить правильный уровень изоляции. При отсутствии констрейнта хибер сам не разгребет, и тд
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174231
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
lor2я нашел вот это:
setProperty("hibernate.connection.isolation", "2");

Это вам не надо.

lor2где уровень указвается. и да, что то читал насчет версионинга но в инете инфы как то маловато. значит люди с этим не сталкиваются.
Все сталкиваются. Вы, возможно, не так искали.


lor2в практике же "посчитать количество помидор и отнять помидоры" это слишком коротакая транзакция и может действительно с этим по этой причине и не сталкиваются.
Кстати, это хорошее дополнение к моему комментарию выше. Для короткой транзакции пессимистичная блокировка позволительна.
Для длинной же "вычитать кол-во доступных помидоров, затем через N минут закомитить измененний" пессимистичная блокировка не подходит вообще.

lor2скулем пользвоаться бы не хотелось по возможности.

Почему?

lor2касательно аннотации @Version тоже не совсем ясно для меня как оно работает. я что ставлю эту аннотацию и проблема решена чтоль?
Нет. У тебя есть запись Помидоры, 20, v1. Её вычитывают 2 клиента. Затем оба пытаются обновить её:
-15 (Помидоры, 5, v2)
-10 (Помидоры, 10, v2)
Первый успевает, второй получает исключение, потому что в базе v2 и у него v2.
v2 это поле помеченое @Version.


lor2чуть ранее я задавал тут похожий вопрос - мне сказали - когда засовываешь всё в одну транзакцию то типа "так не будет" :)
Сложно дать точный ответ на помидорах. Нужно точное описание процесса и транзакции.
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174235
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
да, про уровень изоляции транзакций это я не в ту степь немного, но опять же зависит от кода
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174236
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
забыл ник
Код: java
1.
2.
3.
4.
int count = select count of tomato
if (count > order.count) {
    update pomidors set count = count - order.count
}



Можно даже что-то типа
UPDATE pomidors SET count = count - order.count WHERE count >= order.count.
И потом смотреть количество измененных записей.
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174238
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowiczзабыл ник
Код: java
1.
2.
3.
4.
int count = select count of tomato
if (count > order.count) {
    update pomidors set count = count - order.count
}



Можно даже что-то типа
UPDATE pomidors SET count = count - order.count WHERE count >= order.count.
И потом смотреть количество измененных записей.

И правда, отличный вариант
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174249
lor2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
так вот и всё описание: есть объект класса помидоры. у помидоров есть поле "количество". есть объект класса резервация, там есть тоже поле "количество".

у помидора связь с резервацией ван ту мени. (если это важно)

процесс выглядит так
1) загружаем в помять объект помидор. проверяем количество помидоров на складе по полю "количество" в объекте помидор, если количество помидоров больше количества в брони то

2а) отнимаем от объекта помидор количество в брони и обновляем объект помидор в базе. следом сохраняем резервацию.
2б) если в брони больше чем остатков то выходим с сообщением что бронь неверна.

собссно всё.


если ты говори что при помечении поля аннотацией @Version у меня произойдет ексцепшн на момент коммита, то в принципе - тут уже ясно что делать. скажем юзеру извини - долго собирался.

теперь вопрос - как устанавливать тип блокировки в хибере на отдельные транзакции? :)
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174254
lor2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Blazkowicz,

может быть, но блин. неужель без скуля никак не получится обойтись? :) я ведь даже выборки по критериям стараюсь делать. чтоб скуэля по минимуму.
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174269
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
lor2,

В вашем случае хибер сам не разрулит, даже с аннотацией Version. Вариантов несколько:

1) Если не трогать код, то достаточно добавить check constraint на поле количество помидоров. Тогда при коммите вылетит эксепшен вы словите и покажете юзеру
2) Поменять код, и использовать прямой sql UPDATE pomidors SET count = count - order.count WHERE count >= order.count. Если количество проапдейченых строк = 1 то ок, если 0 - говорите юзеру извини
3) Вначале залочить объект помидор session.buildLockRequest(new LockOptions(LockMode.PESSIMISTIC_READ)).lock(tomato);
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174272
lor2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
вот. у нас две таблицы итемПати (серия) и резервация (резервация)

автор @Transactional
public void addReservation(Reservation reservation) {
ItemParty itemParty = daoItemParty.getItemPartyById(reservation.getItemParty().getId());
if(itemParty.getAmount()>reservation.getAmount()){

dao.addReservation(reservation);
}else {
...шлем в пень....
}

}
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174282
lor2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
забыл никlor2,

В вашем случае хибер сам не разрулит, даже с аннотацией Version. Вариантов несколько:

1) Если не трогать код, то достаточно добавить check constraint на поле количество помидоров. Тогда при коммите вылетит эксепшен вы словите и покажете юзеру
2) Поменять код, и использовать прямой sql UPDATE pomidors SET count = count - order.count WHERE count >= order.count. Если количество проапдейченых строк = 1 то ок, если 0 - говорите юзеру извини
3) Вначале залочить объект помидор session.buildLockRequest(new LockOptions(LockMode.PESSIMISTIC_READ)).lock(tomato);

выходит в процедуру редактирования сущности итемпати я вставляю вот это?
автор public void editItemParty(ItemParty itemParty) {
// sessionFactory.getCurrentSession().buildLockRequest(new LockOptions(LockMode.PESSIMISTIC_READ)).lock(itemParty);??
sessionFactory.getCurrentSession().update(itemParty);

}
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174294
lor2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
пардон, вот так вот :

автор@Transactional
public void addReservation(Reservation reservation) {
ItemParty itemParty = daoItemParty.getItemPartyById(reservation.getItemParty().getId());
if(itemParty.getAmount()>reservation.getAmount()){
itemParty.setAmount(itemParty.getAmount()-reservation.getAmount());
dao.addReservation(reservation);
}else {
...шлем в пень....
}

}
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174297
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
lor2теперь вопрос - как устанавливать тип блокировки в хибере на отдельные транзакции? :)
Не понял вопроса. Добавляешь поле и @Version на него и получаешь результат. Какие ещё "отдельные транзакции"?
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174299
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
забыл никВ вашем случае хибер сам не разрулит, даже с аннотацией Version.
Почему нет?
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174302
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowiczзабыл никВ вашем случае хибер сам не разрулит, даже с аннотацией Version.
Почему нет?

Потому что было 30 помидоров, один заказ на 10 и второй на 10, оба вычитали что каунт = 30, первый успешно закомиттил и коунт стал 20, второй пробует сделать update count where count =30, получает отлуп, и тут уже надо разбираться? Нет ну можно замутить какой-то retry, но это усложнение с неочевидным профитом. Те варианты проще
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174333
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
забыл никПотому что было 30 помидоров, один заказ на 10 и второй на 10, оба вычитали что каунт = 30, первый успешно закомиттил и коунт стал 20, второй пробует сделать update count where count =30, получает отлуп, и тут уже надо разбираться? Нет ну можно замутить какой-то retry, но это усложнение с неочевидным профитом. Те варианты проще
Ну, да. Всё зависит от системы и требований.
Имеет ли смысл показать сообщение пользователю "ой а помидоров уже 20, а не 30", если он хотел резервировать всего 10? Где-то имеет, а где-то нет. Зависит от требований.
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174337
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
lor2может быть, но блин. неужель без скуля никак не получится обойтись? :) я ведь даже выборки по критериям стараюсь делать. чтоб скуэля по минимуму.
На HQL/JPQL можно запрос написать. Стремиться к критериям ради критериев? Зачем? HQL проще читается.
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174349
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
забыл никПотому что было 30 помидоров, один заказ на 10 и второй на 10, оба вычитали что каунт = 30, первый успешно закомиттил и коунт стал 20, второй пробует сделать update count where count =30, получает отлуп, и тут уже надо разбираться? Нет ну можно замутить какой-то retry, но это усложнение с неочевидным профитом. Те варианты проще
В крупных системах так обычно не делают.

Делают таблицу транзакций + состояние (по разному, например после проведения последней транзакции), часто с разбивкой по ячейкам хранения.

забыл никupdate count where count =30, получает отлуп, и тут уже надо разбираться? Нет ну можно замутить какой-то retry, но это усложнение с неочевидным профитом. Те варианты проще
Недостаток оптимистичной блокировки.

Писсимистичная просто будет стоять и ждать, пока запись разблокируется. Т.е.

SELECT count FROM inventory_total WHERE item_id = :id FOR UPDATE -- Поставили блокировку
-- Какая-то логика
UPDATE SET count=new_count inventory_total WHERE item_id = :ID
COMMIT

никаких exception не будет
...
Рейтинг: 0 / 0
Hibernate разрешение конфликтных ситуаций?
    #39174353
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Leonid Kudryavtsev,

так а я про что? Вы меня наверное с ТС перепутали, вариантов множество, все зависит от системы и требований. Я просто отвечал почему оптимистичная блокировка здесь не самый лучший вариант
...
Рейтинг: 0 / 0
25 сообщений из 108, страница 1 из 5
Форумы / Java [игнор отключен] [закрыт для гостей] / Hibernate разрешение конфликтных ситуаций?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]