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

родитель:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
   < class  name="ClientBase" table="ClientBase" lazy="true"> 
       
      <id name="id" type="long"> 
          <generator  class ="sequence"> 
                          <param name="sequence">USERS_ID_SEQ</param>      
                        </generator> 
      </id> 

                <property name="name" type="string" length="30" unique-key="aaa" /> 
                <property name="sname" type="string" length="30" unique-key="aaa" /> 
                

        <many-to-one name="location" column="location_id" 
                      class ="Location"/> 


                <set name="Phones" table="PHONES" cascade="all"> 
                  <key column="CLIENT_ID" /> 
                  <one-to-many  class ="Phone" /> 
                </set> 


   </ class > 

собственно класс для set-а
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
    < class  name="Phone" table="PHONES">
        <id name="id" column="id" type="long">
            <generator  class ="native"/>
        </id>
        <property name="phone" type="string" length="20"/>
        <property name="type" type="integer"/>
    </ class >

код:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
           final  SessionFactory sfactory = cfg.buildSessionFactory(); 
          Session session =  sfactory.openSession(); 
          Transaction txn = session.beginTransaction(); 

          ClientBase cb= new  ClientBase(); 
          session.persist(cb); 
          Phone ph= new  Phone(); 
          ph.setPhone("1111111"); 
          cb.getPhones().add(ph); 
          session.persist(ph); 
          Phone ph1= new  Phone(); 
          ph1.setPhone("2222222"); 
          cb.getPhones().add(ph1); 
          session.persist(ph1); 
ph1.setPhone("22222223333"); 

          session.flush(); 
          txn.commit(); 
          txn.begin(); 
          ll.info("Start delete Client");
          session.delete(cb); 
          session.flush(); 
          txn.commit(); 
на момент исполенния session.flush();
после 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 делать именно это??

я не понимаю как с этим можно бороться.
Поясните пожалуста!
Большое Спасибо!
...
Рейтинг: 0 / 0
Hibernate. лишние delete. как бороться?
    #33650563
Sleepy_PIP
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
попробовал как
Код: plaintext
1.
2.
3.
4.
5.
          ll.info("Start delete Client");
          cb.getPhones().clear();
          session.delete(cb);
          session.flush();
          txn.commit();

получил еще более не понятный для меня результат.
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.
          ll.info("Start delete Client");
          cb.getPhones().remove(ph);
          session.delete(cb);
          session.flush();
          txn.commit();

т.е. явно удаляем один известный 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 будут + еще и мой код ...
что-то не так. не должно быть так. а?
...
Рейтинг: 0 / 0
Hibernate. лишние delete. как бороться?
    #33650599
М.Голованов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В общем, вы, наверное, поняли, что используя Hibernate, меняете простоту и логичность кода на производительность. Ваш самый первый код

txn.begin();
session.delete(cb);
session.flush();
txn.commit();

прост и логичен. Но он же явно (как вы и продемонстрировали) не оптимален. Плата за простоту.

Поэтому я, кстати, стараюсь избегать использования декларативных отношений. Все контролирую в коде - ценой его некоторого усложнения, но получаю более высокую производительность.
...
Рейтинг: 0 / 0
Hibernate. лишние delete. как бороться?
    #33650605
funikovyuri
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если я правильно понял:
2й пример
Код: plaintext
1.
2.
3.
4.
 ll.info("Start delete Client");
          cb.getPhones().clear();
          session.delete(cb);
          session.flush();
          txn.commit();

Вы сначала отсоединяете экземпляры объектов Phone от коллекции ClientBase.phones. Именно отсоединяете, а не удаляете (не делаете транзиентными). В этом случае hibernate верно делает сначала update ... set ... null, а потом выполняет delete ... который соответствует session.delete(cb);

авторт.е. результат плачевен - Phones записи просто все остались.
И это правильно, т.к. вы их не удаляли с помощью session.delete()!

1й пример
Код: plaintext
1.
2.
3.
4.
 ll.info("Start delete Client");
          cb.getPhones().remove(ph);
          session.delete(cb);
          session.flush();
          txn.commit();

Тут дело в том, что вы используете 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.
  ll.info("Start delete Client");
          cb.getPhones().remove(ph);
          session.delete(cb);
          session.flush();
          txn.commit();
Я, если честно, сразу точно сказать не берусь. Но, похоже, что hibernate, кроме того, что я сказал про первый ваш пример, еще и выполнил оптимизацию и слил в один два запроса update set client_id=null where id=? и update set client_d=null where client_id=?. Что кстати абсолютно корректно.
...
Рейтинг: 0 / 0
Hibernate. лишние delete. как бороться?
    #33650613
Sleepy_PIP
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
М.ГоловановВ общем, вы, наверное, поняли, что используя Hibernate, меняете простоту и логичность кода на производительность. Ваш самый первый код

txn.begin();
session.delete(cb);
session.flush();
txn.commit();

прост и логичен. Но он же явно (как вы и продемонстрировали) не оптимален. Плата за простоту.

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

но тогда вывод прост до безобразия. Пишем СВОИ классы так, что-бы они сами могли получать и сохранять свои члены через JDBC.
При этом пользуем native SQL - который на показанном примере и своих кодах будет на несколько порядков эффективнее Hibernate.
Так в чем-же дело? зачем тогда Hibernate? для задач не более чем клиент и его телефоны?.
Ведь я взял самое простое! и столкнулся с не объяснимым с точки зрения RDB и SQL да и вообще простейшей логики ...
я опять не понимаю :(.
Я зря изучаю Hibernate? - я что-то упустил скорее всего важное ...
...
Рейтинг: 0 / 0
Hibernate. лишние delete. как бороться?
    #33650623
Sleepy_PIP
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
простейший пример - клиент и его мессаги в построчном хранении в другой таблице.
итого - как поступить дабы избежать удаления строк в таблице мессагов каждую отдельный delete ...
...
Рейтинг: 0 / 0
Hibernate. лишние delete. как бороться?
    #33650625
Sleepy_PIP
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
funikovyuriЕсли я правильно понял:
2й пример
Код: plaintext
1.
2.
3.
4.
 ll.info("Start delete Client");
          cb.getPhones().clear();
          session.delete(cb);
          session.flush();
          txn.commit();

Вы сначала отсоединяете экземпляры объектов Phone от коллекции ClientBase.phones. Именно отсоединяете, а не удаляете (не делаете транзиентными). В этом случае hibernate верно делает сначала update ... set ... null, а потом выполняет delete ... который соответствует session.delete(cb);

авторт.е. результат плачевен - Phones записи просто все остались.
И это правильно, т.к. вы их не удаляли с помощью session.delete()!

1й пример
Код: plaintext
1.
2.
3.
4.
 ll.info("Start delete Client");
          cb.getPhones().remove(ph);
          session.delete(cb);
          session.flush();
          txn.commit();

Тут дело в том, что вы используете 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.
  ll.info("Start delete Client");
          cb.getPhones().remove(ph);
          session.delete(cb);
          session.flush();
          txn.commit();
Я, если честно, сразу точно сказать не берусь. Но, похоже, что hibernate, кроме того, что я сказал про первый ваш пример, еще и выполнил оптимизацию и слил в один два запроса update set client_id=null where id=? и update set client_d=null where client_id=?. Что кстати абсолютно корректно.

1. бидирекшенал мне на надо, да он и не предусмортен.
2. в обеих таблицах есть вся достаточная информация для массированного удаления одним SQL выражением.
3. в классе clientbase есть вся достаточная информация для удаления Set-а одним SQL выражением.
4. в маппинге есть вся информация, достаточная для удаления всего Set-а одним SQL выражением как того требует исполняемый код.

Но однако задумка другая.
Может быть это связано с презистентностью объектов типа Phone? - которые необходимо удалять поштучно, т.к. может сработать к примеру finaly? или что там еще при удалении объекта по GC (ну как пример)? ... может быть в этом собака зарыта? - ведь Hibernate в принципе не может знать что для каждого конкр. объекта Phone выполнится при его удалении? в связи с чем удаление объекта Phone производится _до_ удаления записи из БД?.
я на верном пути? ....
...
Рейтинг: 0 / 0
Hibernate. лишние delete. как бороться?
    #33650631
Sleepy_PIP
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
причем это подтверждает то, что удаление записи до удаления объекта _будет_ видно в данной сессии. а это может оказаться не верным с точки зрения удаляемого объекта.
Если все действительно так. все очень не здорово ... мало того что SQL в развитых системах может быть ну очень сложным как по доступу, так и по изменению, так тут еще с верху и объектный маппинг. нда ... думать надо, работать надо. будем думать ....
...
Рейтинг: 0 / 0
Hibernate. лишние delete. как бороться?
    #33650845
funikovyuri
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sleepy_PIP

К сожалению вы невнимательно прочитали мое сообщение

авторбидирекшенал мне на надо, да он и не предусмортен.
во-первых, что значит не предусмотрен? во-вторых, я вам пытался показать что у вас в Р-схеме many-to-one, а в объектной one-to-many - это уже концептуально не совсем чисто с точки зрения РБД. А hibernate он очень аккуратно работает следуя реляционному подходу.

авторв обеих таблицах есть вся достаточная информация для массированного удаления одним SQL выражением.

Да в таблицах есть - в классах нет! Еще раз постарайтесь понять, что я писал, и что написано в приведенной документации по hibernate

авторМожет быть это связано с презистентностью объектов типа Phone? - которые необходимо удалять поштучно
нет

ЗЫ hibernate при правильном использовании с БД работает очень эффективно. Нужно только понимать принципы его работы. Я привел описание, почему вы получили именно такое поведение - если вам нужны простые ответы и легкие решения - тогда да - лучше plain jdbc
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Hibernate. лишние delete. как бороться?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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