|
|
|
Hibernate. лишние delete. как бороться?
|
|||
|---|---|---|---|
|
#18+
только не бросайте меня в колючие кусты. учусь .... родитель: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. собственно класс для set-а Код: plaintext 1. 2. 3. 4. 5. 6. 7. код: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. после session.delete(cb); получаем: INFO 6453 [main] com.pip.datadefine.CreateSchema - Start delete Client DEBUG 6469 [main] org.hibernate.SQL - update PHONES set CLIENT_ID=null where CLIENT_ID=? DEBUG 6469 [main] org.hibernate.SQL - delete from PHONES where id=? DEBUG 6469 [main] org.hibernate.SQL - delete from PHONES where id=? DEBUG 6500 [main] org.hibernate.SQL - delete from ClientBase where id=? разумеется - после update PHONES set CLIENT_ID=null where CLIENT_ID=? их уже никак не удалить. плохо :(. а нет что-б сказать в первую очередь delete from PHONES where CLIENT_ID=? Как бы заставить Hibernate делать именно это?? я не понимаю как с этим можно бороться. Поясните пожалуста! Большое Спасибо! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.04.2006, 22:17 |
|
||
|
Hibernate. лишние delete. как бороться?
|
|||
|---|---|---|---|
|
#18+
попробовал как Код: plaintext 1. 2. 3. 4. 5. получил еще более не понятный для меня результат. INFO 19797 [main] com.pip.datadefine.CreateSchema - Start delete Client DEBUG 39375 [main] org.hibernate.SQL - update PHONES set CLIENT_ID=null where CLIENT_ID=? DEBUG 39391 [main] org.hibernate.SQL - delete from ClientBase where id=? не смотря на то что Set Phones предварительно очищен явно. т.е. результат плачевен - Phones записи просто все остались. теперь меняем код опять Код: plaintext 1. 2. 3. 4. 5. т.е. явно удаляем один известный Phone получаем INFO 14875 [main] com.pip.datadefine.CreateSchema - Start delete Client DEBUG 19891 [main] org.hibernate.SQL - update PHONES set CLIENT_ID=null where CLIENT_ID=? DEBUG 19906 [main] org.hibernate.SQL - delete from PHONES where id=? DEBUG 19922 [main] org.hibernate.SQL - delete from ClientBase where id=? 1. опять 25-ть, т.е. сначала update PHONES set CLIENT_ID=null where CLIENT_ID=? - причем заметим! предварительно в Phones было 2 записи, ссылающихся на cb. после такого апдейта мы имеем 2 записи, не ссылающиеся более никуда. после чего удаляем delete from PHONES where id=? одну из них. все. привет. в Phones осталась запись с форином=null и что теперь? так и будет существовать до 3000-го года? причем заметим - при простом удалении cb - так хоть отдельными delete, но весь Set был удален. а тут вообще не понятки какие-то .... т.е. я не понимаю устойчивость коллекций. получается .... т.е. явно как-то это было задумано, но не понятки имеено у меня ... зачем так было задумано. т.е. получается что если я имею связку класса с коллекцией - будь добр - удали все элементы колл. сам ... причем если я их буду к примеру иттерировать и удалять по отдельности - те-же тучи отдельных delete будут + еще и мой код ... что-то не так. не должно быть так. а? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.04.2006, 22:49 |
|
||
|
Hibernate. лишние delete. как бороться?
|
|||
|---|---|---|---|
|
#18+
В общем, вы, наверное, поняли, что используя Hibernate, меняете простоту и логичность кода на производительность. Ваш самый первый код txn.begin(); session.delete(cb); session.flush(); txn.commit(); прост и логичен. Но он же явно (как вы и продемонстрировали) не оптимален. Плата за простоту. Поэтому я, кстати, стараюсь избегать использования декларативных отношений. Все контролирую в коде - ценой его некоторого усложнения, но получаю более высокую производительность. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.04.2006, 23:35 |
|
||
|
Hibernate. лишние delete. как бороться?
|
|||
|---|---|---|---|
|
#18+
Если я правильно понял: 2й пример Код: plaintext 1. 2. 3. 4. Вы сначала отсоединяете экземпляры объектов Phone от коллекции ClientBase.phones. Именно отсоединяете, а не удаляете (не делаете транзиентными). В этом случае hibernate верно делает сначала update ... set ... null, а потом выполняет delete ... который соответствует session.delete(cb); авторт.е. результат плачевен - Phones записи просто все остались. И это правильно, т.к. вы их не удаляли с помощью session.delete()! 1й пример Код: plaintext 1. 2. 3. 4. Тут дело в том, что вы используете unidirectional one-to-many ассоциацию. Так вот в реляционном виде она будет представлена с помощью введения в вашу child entity, т.е. в phone дополнительного атрибута типа parent_id (в вашем случае - client_id). Т.е. смотрите в вашей объектной модели есть коллекция phones и она принадлежит ClientBase, в то время, как в классе Phone ничего о ClientBase не известно. С другой стороны в схеме РБД у вас полностью противоположная ситуация - в таблице phone есть атрибут client_id, а вот таблица для clientbase ничего о коллекции phones не знает. Это очень тонкая ситуация и ноги у нее растут из того что в РБД нет one-to-many, а только many-to-one! Поэтому, когда hibernate удаляет вашего клиента, у которого для phones стоит cascade=all он не может (т.е. может - но это было бы не корректно) выполнить запрос типа delete ... where client_id=? так как с точки зрения класса phone у него такого атрибута просто нет. Поэтому то hibernate сначала отсоединяет нужные экземпляры phones от родителя (т.е. выполняет операцию над коллекцией clientbase.phones), а затем уже удаляет эти объекты по одному. Подробнее см. 21.1. A note about collections Здесь кстати сказано как можно избежать подобной ситуации, если нужно. Теперь же насчет третьего вашего примера: Код: plaintext 1. 2. 3. 4. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.04.2006, 23:41 |
|
||
|
Hibernate. лишние delete. как бороться?
|
|||
|---|---|---|---|
|
#18+
М.ГоловановВ общем, вы, наверное, поняли, что используя Hibernate, меняете простоту и логичность кода на производительность. Ваш самый первый код txn.begin(); session.delete(cb); session.flush(); txn.commit(); прост и логичен. Но он же явно (как вы и продемонстрировали) не оптимален. Плата за простоту. Поэтому я, кстати, стараюсь избегать использования декларативных отношений. Все контролирую в коде - ценой его некоторого усложнения, но получаю более высокую производительность. но тогда вывод прост до безобразия. Пишем СВОИ классы так, что-бы они сами могли получать и сохранять свои члены через JDBC. При этом пользуем native SQL - который на показанном примере и своих кодах будет на несколько порядков эффективнее Hibernate. Так в чем-же дело? зачем тогда Hibernate? для задач не более чем клиент и его телефоны?. Ведь я взял самое простое! и столкнулся с не объяснимым с точки зрения RDB и SQL да и вообще простейшей логики ... я опять не понимаю :(. Я зря изучаю Hibernate? - я что-то упустил скорее всего важное ... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.04.2006, 23:52 |
|
||
|
Hibernate. лишние delete. как бороться?
|
|||
|---|---|---|---|
|
#18+
простейший пример - клиент и его мессаги в построчном хранении в другой таблице. итого - как поступить дабы избежать удаления строк в таблице мессагов каждую отдельный delete ... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2006, 00:03 |
|
||
|
Hibernate. лишние delete. как бороться?
|
|||
|---|---|---|---|
|
#18+
funikovyuriЕсли я правильно понял: 2й пример Код: plaintext 1. 2. 3. 4. Вы сначала отсоединяете экземпляры объектов Phone от коллекции ClientBase.phones. Именно отсоединяете, а не удаляете (не делаете транзиентными). В этом случае hibernate верно делает сначала update ... set ... null, а потом выполняет delete ... который соответствует session.delete(cb); авторт.е. результат плачевен - Phones записи просто все остались. И это правильно, т.к. вы их не удаляли с помощью session.delete()! 1й пример Код: plaintext 1. 2. 3. 4. Тут дело в том, что вы используете unidirectional one-to-many ассоциацию. Так вот в реляционном виде она будет представлена с помощью введения в вашу child entity, т.е. в phone дополнительного атрибута типа parent_id (в вашем случае - client_id). Т.е. смотрите в вашей объектной модели есть коллекция phones и она принадлежит ClientBase, в то время, как в классе Phone ничего о ClientBase не известно. С другой стороны в схеме РБД у вас полностью противоположная ситуация - в таблице phone есть атрибут client_id, а вот таблица для clientbase ничего о коллекции phones не знает. Это очень тонкая ситуация и ноги у нее растут из того что в РБД нет one-to-many, а только many-to-one! Поэтому, когда hibernate удаляет вашего клиента, у которого для phones стоит cascade=all он не может (т.е. может - но это было бы не корректно) выполнить запрос типа delete ... where client_id=? так как с точки зрения класса phone у него такого атрибута просто нет. Поэтому то hibernate сначала отсоединяет нужные экземпляры phones от родителя (т.е. выполняет операцию над коллекцией clientbase.phones), а затем уже удаляет эти объекты по одному. Подробнее см. 21.1. A note about collections Здесь кстати сказано как можно избежать подобной ситуации, если нужно. Теперь же насчет третьего вашего примера: Код: plaintext 1. 2. 3. 4. 1. бидирекшенал мне на надо, да он и не предусмортен. 2. в обеих таблицах есть вся достаточная информация для массированного удаления одним SQL выражением. 3. в классе clientbase есть вся достаточная информация для удаления Set-а одним SQL выражением. 4. в маппинге есть вся информация, достаточная для удаления всего Set-а одним SQL выражением как того требует исполняемый код. Но однако задумка другая. Может быть это связано с презистентностью объектов типа Phone? - которые необходимо удалять поштучно, т.к. может сработать к примеру finaly? или что там еще при удалении объекта по GC (ну как пример)? ... может быть в этом собака зарыта? - ведь Hibernate в принципе не может знать что для каждого конкр. объекта Phone выполнится при его удалении? в связи с чем удаление объекта Phone производится _до_ удаления записи из БД?. я на верном пути? .... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2006, 00:11 |
|
||
|
Hibernate. лишние delete. как бороться?
|
|||
|---|---|---|---|
|
#18+
причем это подтверждает то, что удаление записи до удаления объекта _будет_ видно в данной сессии. а это может оказаться не верным с точки зрения удаляемого объекта. Если все действительно так. все очень не здорово ... мало того что SQL в развитых системах может быть ну очень сложным как по доступу, так и по изменению, так тут еще с верху и объектный маппинг. нда ... думать надо, работать надо. будем думать .... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2006, 00:15 |
|
||
|
Hibernate. лишние delete. как бороться?
|
|||
|---|---|---|---|
|
#18+
Sleepy_PIP К сожалению вы невнимательно прочитали мое сообщение авторбидирекшенал мне на надо, да он и не предусмортен. во-первых, что значит не предусмотрен? во-вторых, я вам пытался показать что у вас в Р-схеме many-to-one, а в объектной one-to-many - это уже концептуально не совсем чисто с точки зрения РБД. А hibernate он очень аккуратно работает следуя реляционному подходу. авторв обеих таблицах есть вся достаточная информация для массированного удаления одним SQL выражением. Да в таблицах есть - в классах нет! Еще раз постарайтесь понять, что я писал, и что написано в приведенной документации по hibernate авторМожет быть это связано с презистентностью объектов типа Phone? - которые необходимо удалять поштучно нет ЗЫ hibernate при правильном использовании с БД работает очень эффективно. Нужно только понимать принципы его работы. Я привел описание, почему вы получили именно такое поведение - если вам нужны простые ответы и легкие решения - тогда да - лучше plain jdbc ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2006, 09:05 |
|
||
|
|

start [/forum/topic.php?fid=59&fpage=737&tid=2149674]: |
0ms |
get settings: |
11ms |
get forum list: |
12ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
39ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
38ms |
get tp. blocked users: |
1ms |
| others: | 246ms |
| total: | 361ms |

| 0 / 0 |
