|
|
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
В hibernate у класса Session есть такие методы merge update saveOrUpdate Описание javaDoc как-то не совсем мне понятно. Можете простыми словами объяснить зачем нужны эти методы, чем они отличаются и как ими правильно пользоваться? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.09.2013, 20:59:07 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
Неразбериха бывает из-за неправильного понятия сессии. Многие думают, что она предназначена только для работы с базой, а на самом деле сессия - это прежде всего кеш. Все, что мы пишем и читаем с помощью сессии, параллельно сохраняется в локальном кеше, и при повторном обращении к объекту не нужен сетевой запрос - объект уже хранится локально. Благодаря правильному использованию кеша, программы, написанные с использованием hibernate, зачастую работают быстрее, чем написанные на чистом jdbc. А теперь смотрим, что происходит. 1) update и saveOrUpdate - 2 разных варианта синхронизации объекта, уже находящегося в сессии, с базой данных. Попросту говоря, объект из кеша сохраняется в базу данных с использованием update-а или insert-a. Есть нюанс: если объекта не было в сессии (detached), то проверяется, а есть ли объект с таким же ключом в локальном кеше. Если есть, то выдается исключение, если нет - пишется в базу и параллельно в кеш. После выполнения update и saveOrUpdate состояния объекта в сессии и в базе совпадают . 2) merge (присоединение) - "обратная" операция. Имеет смысл для отсоединенных (detached) объектов. Например, мы получили в сессии объект, потом сессию закрыли (кеш обнулился), а сам объект где-то сохранили, и даже изменили некоторые поля. Так вот, когда мы пишем Код: java 1. , то происходит следующее: - объект по ключу запрашивается из базы (делается запрос select ... from ...) - получаем заготовку attachedObject; - поля attachedObject-а обновляются значениями полей detachedObject-а - attachedObject сохраняется в кеше, а detachedObject после этого годится только в мусор. То есть в базу идет только select запрос (и insert, если по ключу ничего не найдено). В общем случае, после выполнения merge состояния объекта в сессии и в базе не совпадают Наиболее безопасный сценарий сохранения объекта - присоединить объект к сессии, затем сохранить в базе: Код: java 1. 2. но это лишний select, поэтому, если мы уверены, что объекта нет в сессии, бывает выгоднее сразу detached состояние сохранять в кеш и базу: Код: java 1. 2. 3. как-то так ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.09.2013, 22:14:57 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
ivanra, ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.09.2013, 22:31:25 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
ivanra , Начали вы правильно - многие неправильно понимают сессию. Но дальнейшее объяснение настолько чудовищно неверно, что освежить в голове семантику операций нужно именно вам. ivanraupdate и saveOrUpdate - 2 разных варианта синхронизации объекта, уже находящегося в сессии, с базой данныхНеверно. Эти операции предназначены для того, что бы синхронизировать объект, которого нет в сессии с этой самой сессией. ivanraПопросту говоря, объект из кеша сохраняется в базу данных с использованием update-а или insert-aНеверно. Непосредственно при вызове update или saveOrUpdate запись в СУБД может происходить, а может и не происходить. ivanraЕсть нюанс: если объекта не было в сессии (detached), то проверяется, а есть ли объект с таким же ключом в локальном кеше. Если есть, то выдается исключениеВерно ivanraесли нет - пишется в базу и параллельно в кешНеверно. Пишется только в сессию (кэш). В базу запись пойдет при флаше. ivanraПосле выполнения update и saveOrUpdate состояния объекта в сессии и в базе совпадаютНеверно. Почему - см. выше. ivanramerge (присоединение) - "обратная" операцияНеверно. merge по семантике очень близок к update, они практически идентичны. Главное отличие: если вызвать update, и объект с таким идентификатором уже есть в сессии, то будет брошено исключение, а если вызвать merge - не будет, состояние из детачнутого объекта успешно перенесется в сессию. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.09.2013, 22:41:22 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
DEVcoach, у Вас столько замечаний.... не могли бы полностью написать ваше видение этих функций, а то так всё смешалось. Ну и расщифруйте пожалуйста слово синхронизировать в контексте использования. ========== Я заметил, что при merge() сразу что-то в базу идёт, но если потом ещё update сделать у возвращаемого значения, то и ещё что-то в базу идёт. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.09.2013, 22:55:06 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
questioner , Нет смысла переписывать то, что достаточно просто и лаконично объяснено в пресловутой 10-й главе: http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/objectstate.html Если буду конкретные вопросы после прочтения этого - обращайтесь. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.09.2013, 23:02:30 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
DEVcoach, насчет flash замечание принимаю, но это другая история, да и не спрашивали про него. А насчет остального - смотрите исходники, я написал как именно это работает, а не подстрочный перевод документации. Можно даже и исходники не смотреть, просто включите трассировку: merge() - в базу идут select-ы save(), update(), saveOrUpdate() - в базу идут insert и update ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.09.2013, 23:21:12 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
ivanra, у меня после этого кода Код: java 1. состояние в базе меняется ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.09.2013, 23:38:29 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
ivanra , Цель автора - понять семантику работу этих методов. Вы объяснили ее неверно, я указал на ошибки: 1) Нет гарантий, что непосредственно после вызова update, saveOrUpdate или merge что-то тут же измениться в базе. Это крайне важно. 2) merge и update это не "обратные", а практически идентичные операции. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.09.2013, 00:04:21 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
Кстати, вот еще одна ошибка: Код: java 1. 2. Второй апдейт здесь не то, что не нужен, а он скорее всего даже эксепшн вызовет. Как только мы привязали объект к сессии, его не нужно потом явно сохранять. Например: Код: java 1. 2. сохранит изменение имени в базу без явного вызова каких-либо методов сессии. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.09.2013, 00:08:46 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
Господа, Вы меня запутали)) Код: java 1. 2. могу только добавить, что у меня такой код не вызывает никаких эксепшенов(в моем конкретно случае). я вот вижу только, что у merge всегда берется в расчёт возвращаемое значение а у апдейт нет... ну и кстати Код: java 1. если оставить только это строчку у меня в базу записывается не то, что в объекте object, точнее не всё. Если бы Вы объяснили это по такому принципу как -состояние до -входные параметры -производимые манипуляции в функции -выходные параметры -состоянии после было бы куда яснее. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.09.2013, 00:40:26 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
questioner, - Merge используется для отлова и исключения NonUniqueObjectException при деаттачнутых объектах. - Как только закрыли сессию, хибер перестаёт ими управлять - Для обратного присоединения к хиберу и есть Merge - Возврат - объект с которым нужно работать дальше. Сделай пример деаттачнутого объекта и логи вызова SQL. Что гадать на кофейной гуще. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.09.2013, 11:18:25 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
Petro123questioner, - Merge используется для отлова и исключения NonUniqueObjectException при деаттачнутых объектах. - Как только закрыли сессию, хибер перестаёт ими управлять - Для обратного присоединения к хиберу и есть Merge - Возврат - объект с которым нужно работать дальше. Сделай пример деаттачнутого объекта и логи вызова SQL. Что гадать на кофейной гуще. Собственно так и сделал, чтобы не быть голословным. Просто я смотрю даже у "гуру" мнения расходятся. вот такой маппинг: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. вот такой код: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. вот такой лог: Код: java 1. 2. 3. 4. 5. 6. Ну это к слову, что в базу пишется в базу после merge() Ну и про присоединение детачнутых объектов я согласен. Код: java 1. 2. Так пишешь и всё работает. Но как то я пока целостной картины понять не могу как это всё происходит. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.09.2013, 11:52:49 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
если конкретнее сформулировать вопрос: почему после merge() иногда что-то в базу идёт подобное апдейту, но результат Код: java 1. не равен(как минимум не всегда) Код: java 1. 2. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.09.2013, 11:55:37 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
questioner Код: java 1. 2. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.09.2013, 11:58:48 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
questionerПросто я смотрю даже у "гуру" мнения расходятся. просто отсоединять объекты - лишний геморрой. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.09.2013, 11:59:56 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
questioner , Стоп, а что вас не устраивает то в merge? Вы уже неоднократно упоминали, что у вас сохранилось "не все". Вопрос такой: что именно не сохранилось? В приведенном вами коде все четко: у вас есть many-to-many отношение, вы добавили связь студен-препод, эта связь сохранилась в СУБД, все корректно и ожидаемо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.09.2013, 12:04:22 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
cdtyjv questioner , Стоп, а что вас не устраивает то в merge? Вы уже неоднократно упоминали, что у вас сохранилось "не все". Вопрос такой: что именно не сохранилось? В приведенном вами коде все четко: у вас есть many-to-many отношение, вы добавили связь студен-препод, эта связь сохранилась в СУБД, все корректно и ожидаемо. Иногда, чтобы добиться такого результат надо писать конструкцию вида: Код: java 1. 2. непонятно когда надо, а когда нет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.09.2013, 12:06:47 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
questioner, Код: java 1. 2. для пущей понятности лучше даже так напишу ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.09.2013, 12:07:56 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
questioner , Так не пойдет. Вы сейчас привели пример, когда все работает без update, как то и должно быть. Если у вас что-то не работает, то приведите конкретный пример. Корректную семантику этих операций я вам уже объяснил, ссылку на документацию дал. Я продолжаю настаивать на том, что merge + update это глупость. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.09.2013, 12:15:04 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
cdtyjv questioner , Так не пойдет. Вы сейчас привели пример, когда все работает без update, как то и должно быть. Если у вас что-то не работает, то приведите конкретный пример. Корректную семантику этих операций я вам уже объяснил, ссылку на документацию дал. Я продолжаю настаивать на том, что merge + update это глупость. Вынужден с Вами согласиться. Просто мне казалось вчера, на проекте посложнее, что это влияло. В общем если выловлю различие - напишу. То есть к merge стоит относиться так - "хибернейт сохрани в базу именно то, что аргумент у merge - он правильный, если есть другие в сессии инстансы - забей на них" ? ну и что же всё таки он тогда возвращает....и зачем? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.09.2013, 12:32:48 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
questioner, повторяю, вся работа идет с кешем, и состояние кеша записывается в базу во время session.flush(). Причем даже не обязательно вызывать session.flush(), поскольку по умолчанию flushMode сессии равен FlushMode.AUTO, и, например, при коммите транзакции (session.getTransaction().commit();) кеш предварительно будет записан. А насчет merge() и update() DEVcoach прав в том смысле, что для кеша это очень похожие операции, но для базы они - разные. update() - объект сохраняется в сессию и "планируется" операция sql update во время flush() merge() - объект ищется в сессии, если нет - загружается из базы (немедленный sql select), обновляется полями detached инстанса, и далее все то же самое что и в update(). И в том и другом случае планируется sql update, но не факт, что он будет выполнен (например, при FlushMode.MANUAL забыли сделать flush()). Но для merge() обязательно выполняется sql select, при любом FlushMode. В принципе, получается что достаточно делать Код: java 1. Но но в некоторых случаях у меня это не работало (при работе с коллекциями и транзитивными связями), а при заключительном update() - заработало Код: java 1. 2. 3. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.09.2013, 12:37:54 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
questionerТо есть к merge стоит относиться так - "хибернейт сохрани в базу именно то, что аргумент у merge - он правильный, если есть другие в сессии инстансы - забей на них" ? ну и что же всё таки он тогда возвращает....и зачем?Нет, не так. Еще раз: до тех пор, пока не был вызван флаш (руками, или автоматически по какой-то причине), ни один метод Хибернейта не гарантирует вам, что что-то будет сохранено в базу . Поймите, сессия - это кэш, в котором хранится информация об изменениях определенных объектов. И этот кэш синхронизируется с базой только по флашу. А пока флаша нет, все изменения храняться исключительно в памяти. Метод update говорит Хиберу: 1) Проверь, есть ли у тебя объект с таким ID в сессии. 2) Если нет, то загрузи этот объект из базы в память, а потом перенеси значения полей из объекта-аргумент в тот объект, который загрузил. 3) Если есть - брось эксепшн. Точка. Никакого сохранения в базу нет. Метод merge говорит Хиберу: 1) Проверь, есть ли у тебя объект с таким ID в сессии. 2) Если нет, то загрузи этот объект из базы в память, а потом перенеси значения полей из объекта-аргумента в тот объект, который загрузил (сесионный объект). 3) Если есть, то просто перенеси состояние из объекта-аргумента в сессионный объект. 4) Верни сессионный объект. Точка. Никакого сохранения в базу нет. Вот один пример использования merge, корректный: Код: java 1. 2. 3. 4. 5. 6. 7. student0 - сессионный объект. Все изменения, которые я в него внес, пока была активна сессия, автоматически сохраняться в базу. То есть, при комите транзакции у него будет имя "Ivan". А вот некорректный пример: Код: java 1. 2. 3. 4. 5. 6. 7. Тут я изменил имя у несессионного объекта. А потому это изменение не сохранится базу. Вы почему-то упорно не хотите читать документацию Хибера. Там это в десятки раз лучше разжевано, чем я вам сейчас объясняю. И уж точно в документации нет ошибок. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.09.2013, 12:47:24 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
cdtyjv3) Если есть - брось эксепшн. +1 NonUniqueObjectException ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.09.2013, 12:51:07 |
|
||
|
Hibernate. merge update saveOrUpdate
|
|||
|---|---|---|---|
|
#18+
ivanra, авторmerge() - объект ищется в сессии, если нет - загружается из базы (немедленный sql select), обновляется полями detached инстанса, и далее все то же самое что и в update(). непонятно где вы у if скобки ставите) 1. объект в сессии: Если есть, то данные из аргумента merge() копируются в персистентный объект. 2.объект не в сессии: объект добавляется в сессию из базы иавтор данные из аргумента merge() копируются в персистентный объект 3. делается update в терминах sql Я так понял. это правильно? ну и с возвращаемым значением хотелось бы таки разобраться - оно же вроде как персистентное. не? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.09.2013, 12:52:55 |
|
||
|
|

start [/forum/topic.php?fid=59&msg=38398615&tid=2128541]: |
0ms |
get settings: |
17ms |
get forum list: |
25ms |
check forum access: |
8ms |
check topic access: |
8ms |
track hit: |
308ms |
get topic data: |
21ms |
get forum data: |
3ms |
get page messages: |
87ms |
get tp. blocked users: |
2ms |
| others: | 316ms |
| total: | 795ms |

| 0 / 0 |
