|
|
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
допустим у меня есть код внутри транзакции: бронирование помидоров на складе. 1) проверяем остатки помидоров на складе. если надо меньше помидоров чем остатки то - бронируем и вычитаем из остатков. если больше - то отказ. ---конец--- теперь у меня допустим, на складе 20 помидоров. идет первая транзакция - бронируем 15 помидоров. вторая транзакция - бронируем 10 помидоров. если они последовательно выполняются у нас получается что проходит первый бронькнул 15 остатки 5 второму - отказ. если они идут одновременно: допустим, оба сделали проверку, оба получили тру. первый тяпнул 15 второй тяпнул 10 на выходе получаем минус 5??? как в данном случае пройдет конфликт? при условии что проверка и коммит внутри одной транзакции. мне сказали что там какой то момент с версионированием, проходит оптимистичная блокировка. но что то толком не нашел инфы об этом в инете. или ни у кого такого не возникает и хибер сам разводит всё? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 13:58 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
lor2, вам надо почитать про уровни изоляции транзакций. Вам скорее всего подойдет READ_COMMITTED ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 14:05 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
забыл ник, хорошо, значит получается в конфиге по умолчанию такой вариант произойти может да? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 14:09 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
lor2забыл ник, хорошо, значит получается в конфиге по умолчанию такой вариант произойти может да? Я точно не помню, врядли READ_UNCOMMITED стоит по дефолту, скорее всего как раз READ_COMMITTED, если вы только сами не переопределили. Отвечая на ваш вопрос - хорошо что вы об этом задумываетесь, но хибер разрулит в вашем случае. в отличие от plain jdbc(правда и там можно выставить Connection autoCommit=false). Хотя я тут подумал, смотря еще какой у вас код, можете показать sql? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 14:15 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
если они идут одновременно: допустим, оба сделали проверку, оба получили тру. первый тяпнул 15 второй тяпнул 10 на выходе получаем минус 5??? Что значит "тяпнул" ? Если заблокировать, то нет, не будет - т.к. второй не сможет заблокировать уже заблокированное. Будет exception ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 14:17 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
Нет, Hibernate ничего сам не разрулит. При этом Hibernate это только инструмент, и прежде чем вы его начнете применять, хорошо бы понимать как он работает. Поэтому для начала нужно понять две вещи 1) Теория заключается в том что надо выбрать между - Пессимистической блокировкой, которая на уровне БД выглядит как SELECT FOR UPDATE. (Блокировка простая и надежная, но она выстраивает запросы в очередь и под высокой нагрузкой и при большой конкуренции начинаются сложности.) ... и оптимистичной блокировкой, которая достаточно просто реализована в хибере в виде @Version поля. Обе транзакции вычитывают свободные помидоры, обе пытаются их отнять от общего количества, но если это происходит одновременно, то одна из транзакций выхватывает исключения оптимистической блокировки. И уже вам как кодеру нужно решить что вы делаете с этим исключением. Это решение хорошее, но нужно правильно продумывать обработку исключения. 2) Практика же иногда предлагает на много более простые решения, как например, SQL запрос выборки с одновременной валидацией значения. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 14:17 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
я нашел вот это: setProperty("hibernate.connection.isolation", "2"); где уровень указвается. и да, что то читал насчет версионинга но в инете инфы как то маловато. значит люди с этим не сталкиваются. в практике же "посчитать количество помидор и отнять помидоры" это слишком коротакая транзакция и может действительно с этим по этой причине и не сталкиваются. скулем пользвоаться бы не хотелось по возможности. касательно аннотации @Version тоже не совсем ясно для меня как оно работает. я что ставлю эту аннотацию и проблема решена чтоль? чуть ранее я задавал тут похожий вопрос - мне сказали - когда засовываешь всё в одну транзакцию то типа "так не будет" :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 14:21 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
lor2я нашел вот это: setProperty("hibernate.connection.isolation", "2"); где уровень указвается. и да, что то читал насчет версионинга но в инете инфы как то маловато. значит люди с этим не сталкиваются. в практике же "посчитать количество помидор и отнять помидоры" это слишком коротакая транзакция и может действительно с этим по этой причине и не сталкиваются. скулем пользвоаться бы не хотелось по возможности. касательно аннотации @Version тоже не совсем ясно для меня как оно работает. я что ставлю эту аннотацию и проблема решена чтоль? чуть ранее я задавал тут похожий вопрос - мне сказали - когда засовываешь всё в одну транзакцию то типа "так не будет" :) Опять же, смотря что вы подразумеваете под посчитать помидоры и отнять. Как это реализовано? В протейшем случае если есть таблица помидоры, и у нее есть поле количество а ваш код выглядит так: Код: java 1. 2. 3. 4. и есть check constraint что поле count не может быть < 0, то достаточно выставить правильный уровень изоляции. При отсутствии констрейнта хибер сам не разгребет, и тд ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 14:27 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
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чуть ранее я задавал тут похожий вопрос - мне сказали - когда засовываешь всё в одну транзакцию то типа "так не будет" :) Сложно дать точный ответ на помидорах. Нужно точное описание процесса и транзакции. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 14:29 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
да, про уровень изоляции транзакций это я не в ту степь немного, но опять же зависит от кода ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 14:31 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
забыл ник Код: java 1. 2. 3. 4. Можно даже что-то типа UPDATE pomidors SET count = count - order.count WHERE count >= order.count. И потом смотреть количество измененных записей. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 14:31 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
Blazkowiczзабыл ник Код: java 1. 2. 3. 4. Можно даже что-то типа UPDATE pomidors SET count = count - order.count WHERE count >= order.count. И потом смотреть количество измененных записей. И правда, отличный вариант ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 14:31 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
так вот и всё описание: есть объект класса помидоры. у помидоров есть поле "количество". есть объект класса резервация, там есть тоже поле "количество". у помидора связь с резервацией ван ту мени. (если это важно) процесс выглядит так 1) загружаем в помять объект помидор. проверяем количество помидоров на складе по полю "количество" в объекте помидор, если количество помидоров больше количества в брони то 2а) отнимаем от объекта помидор количество в брони и обновляем объект помидор в базе. следом сохраняем резервацию. 2б) если в брони больше чем остатков то выходим с сообщением что бронь неверна. собссно всё. если ты говори что при помечении поля аннотацией @Version у меня произойдет ексцепшн на момент коммита, то в принципе - тут уже ясно что делать. скажем юзеру извини - долго собирался. теперь вопрос - как устанавливать тип блокировки в хибере на отдельные транзакции? :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 14:38 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, может быть, но блин. неужель без скуля никак не получится обойтись? :) я ведь даже выборки по критериям стараюсь делать. чтоб скуэля по минимуму. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 14:40 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
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); ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 14:46 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
вот. у нас две таблицы итемПати (серия) и резервация (резервация) автор @Transactional public void addReservation(Reservation reservation) { ItemParty itemParty = daoItemParty.getItemPartyById(reservation.getItemParty().getId()); if(itemParty.getAmount()>reservation.getAmount()){ dao.addReservation(reservation); }else { ...шлем в пень.... } } ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 14:48 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
забыл ник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); } ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 14:52 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
пардон, вот так вот : автор@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 { ...шлем в пень.... } } ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 14:57 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
lor2теперь вопрос - как устанавливать тип блокировки в хибере на отдельные транзакции? :) Не понял вопроса. Добавляешь поле и @Version на него и получаешь результат. Какие ещё "отдельные транзакции"? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 14:58 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
забыл никВ вашем случае хибер сам не разрулит, даже с аннотацией Version. Почему нет? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 14:59 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
Blazkowiczзабыл никВ вашем случае хибер сам не разрулит, даже с аннотацией Version. Почему нет? Потому что было 30 помидоров, один заказ на 10 и второй на 10, оба вычитали что каунт = 30, первый успешно закомиттил и коунт стал 20, второй пробует сделать update count where count =30, получает отлуп, и тут уже надо разбираться? Нет ну можно замутить какой-то retry, но это усложнение с неочевидным профитом. Те варианты проще ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 15:02 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
забыл никПотому что было 30 помидоров, один заказ на 10 и второй на 10, оба вычитали что каунт = 30, первый успешно закомиттил и коунт стал 20, второй пробует сделать update count where count =30, получает отлуп, и тут уже надо разбираться? Нет ну можно замутить какой-то retry, но это усложнение с неочевидным профитом. Те варианты проще Ну, да. Всё зависит от системы и требований. Имеет ли смысл показать сообщение пользователю "ой а помидоров уже 20, а не 30", если он хотел резервировать всего 10? Где-то имеет, а где-то нет. Зависит от требований. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 15:15 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
lor2может быть, но блин. неужель без скуля никак не получится обойтись? :) я ведь даже выборки по критериям стараюсь делать. чтоб скуэля по минимуму. На HQL/JPQL можно запрос написать. Стремиться к критериям ради критериев? Зачем? HQL проще читается. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 15:16 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
забыл никПотому что было 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 не будет ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 15:21 |
|
||
|
Hibernate разрешение конфликтных ситуаций?
|
|||
|---|---|---|---|
|
#18+
Leonid Kudryavtsev, так а я про что? Вы меня наверное с ТС перепутали, вариантов множество, все зависит от системы и требований. Я просто отвечал почему оптимистичная блокировка здесь не самый лучший вариант ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2016, 15:25 |
|
||
|
|

start [/forum/topic.php?fid=59&fpage=101&tid=2124254]: |
0ms |
get settings: |
9ms |
get forum list: |
17ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
75ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
62ms |
get tp. blocked users: |
1ms |
| others: | 227ms |
| total: | 410ms |

| 0 / 0 |
