Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Java Новый топик    Ответить
 Hibernate обновление коллекции  [new]
Angel13
Member

Откуда: Киев
Сообщений: 156
Господа,

при работе с HIbernate возникла следующая проблема, которая мне, мягко говоря не понятна.

У меня есть два класса:

Справочник кодов:
@Entity
@Table(name="INTEREST_CODE_DICT")
public class InterestCodesDict implements Serializable
{
	@Id
	@Column(name = "CODE_ID")
	private Long codeId;
....
}

и Информация о клиенте. Отношение кодов к клиентам Много ко многим.
@Entity
@Table(name = "CUSTOMER_PROFILE")
@SequenceGenerator(name = "profile_error_seq", sequenceName = "PROFILE_ERROR_SEQ")
@org.hibernate.annotations.Proxy(lazy = true)
public class CustomerProfile {
	@Id
	@Column(name = "CUSTOMER_PROFILE_ID")
	private Long customerProfileId;
....
	@ManyToMany
	@JoinTable(name = "INTEREST_CODES", joinColumns = { @JoinColumn(name = "CUSTOMER_PROFILE_ID") }, inverseJoinColumns = { @JoinColumn(name = "INTEREST_DICT_ID") })
	@Cascade(value = { CascadeType.SAVE_UPDATE })
	private List<InterestCodesDict> interestCodes = new ArrayList<InterestCodesDict>();
}


При добавлении кода в коллекцию, и затем сохранения главного объекта
CustomerProfile profile = ...;		
profile.getInterestCodes().add(...);
dao.update(profile);

У меня получается следующий SQL

delete from public.INTEREST_CODES where CUSTOMER_PROFILE_ID=?
DEBUG[AbstractCollectionPersister.remove] done deleting collection
DEBUG[AbstractCollectionPersister.recreate] Inserting collection: 
DEBUG[SQL.log] insert into public.INTEREST_CODES (CUSTOMER_PROFILE_ID, INTEREST_DICT_ID) values (?, ?)
DEBUG[AbstractBatcher.prepareBatchStatement] reusing prepared statement
DEBUG[SQL.log] insert into public.INTEREST_CODES (CUSTOMER_PROFILE_ID, INTEREST_DICT_ID) values (?, ?)
DEBUG[AbstractBatcher.prepareBatchStatement] reusing prepared statement
DEBUG[SQL.log] insert into public.INTEREST_CODES (CUSTOMER_PROFILE_ID, INTEREST_DICT_ID) values (?, ?)
DEBUG[AbstractBatcher.prepareBatchStatement] reusing prepared statement
DEBUG[SQL.log] insert into public.INTEREST_CODES (CUSTOMER_PROFILE_ID, INTEREST_DICT_ID) values (?, ?)
DEBUG[AbstractBatcher.prepareBatchStatement] reusing prepared statement
DEBUG[SQL.log] insert into public.INTEREST_CODES (CUSTOMER_PROFILE_ID, INTEREST_DICT_ID) values (?, ?)

То есть Hibernate мне зачем-то полностью удаляет все дочерние записи, а потом вставляет их заново, но уже изменённые. Это нормально?
Есть какие-то способы заставить его вносить только изменения а не просто перезаписывать всё?
25 июл 07, 20:36    [4436466]     Ответить | Цитировать Сообщить модератору
 Re: Hibernate обновление коллекции  [new]
someone1
Member

Откуда:
Сообщений: 46
Убери @Cascade(value = { CascadeType.SAVE_UPDATE }) ?
25 июл 07, 20:49    [4436491]     Ответить | Цитировать Сообщить модератору
 Re: Hibernate обновление коллекции  [new]
expp
Member

Откуда: spb now
Сообщений: 1240
меня реально задрал этот антипаттерн: http://forum.hibernate.org/viewtopic.php?t=977710 https://www.sql.ru/forum/actualthread.aspx?tid=453741&hl=manytomany+update+delete+insert

hiber и DAO очень разные вещи.

если тут
CustomerProfile profile = ...;
объект вытащили из сессии (или вставили)

то второй раз
dao.update(profile);
это делать не надо
26 июл 07, 10:32    [4437729]     Ответить | Цитировать Сообщить модератору
 Re: Hibernate обновление коллекции  [new]
Angel13
Member

Откуда: Киев
Сообщений: 156
someone1
Убери @Cascade(value = { CascadeType.SAVE_UPDATE }) ?

Не помогает
expp
меня реально задрал этот антипаттерн:

Я не много не понял, о чём вы.

Поиграл с CascadeType - везде один и тот же результат.
26 июл 07, 13:13    [4439017]     Ответить | Цитировать Сообщить модератору
 Re: Hibernate обновление коллекции  [new]
expp
Member

Откуда: spb now
Сообщений: 1240
Angel13

Я не много не понял, о чём вы.

dao.update(profile);
- убери

чаепор а рыкефйрфк фкнынй4цефукпф фп вапи
26 июл 07, 14:07    [4439507]     Ответить | Цитировать Сообщить модератору
 Re: Hibernate обновление коллекции  [new]
Angel13
Member

Откуда: Киев
Сообщений: 156
expp

dao.update(profile);

- убери



Не обращайте внимание на название dao :) Это его какой-то нерадивый программист так обозвал. на самом деле это к DAO паттерну никакого отношения не имеет. Там внутри просто вызывается метод
session.saveOrUpdate(profile); Посему - не могу его убрать, так как именно он сохраняет данные в БД.
26 июл 07, 15:14    [4440146]     Ответить | Цитировать Сообщить модератору
 Re: Hibernate обновление коллекции  [new]
expp
Member

Откуда: spb now
Сообщений: 1240
1. шо происходит тута
CustomerProfile profile = ...;		
2. убери его нах
26 июл 07, 15:44    [4440438]     Ответить | Цитировать Сообщить модератору
 Re: Hibernate обновление коллекции  [new]
vas0
Member

Откуда: Таможенный союз (Россия, Казахстан)
Сообщений: 1160
Angel13
... внутри просто вызывается метод
session.saveOrUpdate(profile); Посему - не могу его убрать, так как именно он сохраняет данные в БД.
все зависит от того в каком у вас состоянии объект profile, если в persitent состоянии то dirty checking происходит автоматом и вам не нужно вызывать saveOrUpdate. Этот метод предназначен для перевода из состония detached в persistent.

Вообще честно говоря hibernate это чуть ли не единственная технология, которые многие начинают использовать, даже не понимая и не пытаясь понять как он работает, прочитав step by step и замапив таблицу на класс, после этого процесс обучения прекращается. И потом начинаются вопросы "Почему мое приложение не летает? Ну и фиговая же у hibernate производитьльность".

Почему то никто не задает вопросы "Я не знаю что такое sql и oracle, но почему мое приложение работает так медленно?"
26 июл 07, 15:52    [4440525]     Ответить | Цитировать Сообщить модератору
 Re: Hibernate обновление коллекции  [new]
Angel13
Member

Откуда: Киев
Сообщений: 156
vas0

Почему то никто не задает вопросы "Я не знаю что такое sql и oracle, но почему мое приложение работает так медленно?"

У меня достаточно много опыта работы с Oracle и SQL :) собственно говоря это моя специальность. Но так получилось что пришлось кодить на JAVA. Поверьте, мне самому дико видеть в комментариях по Hibernate, что "это технология позволяет разработчику вообще не думать о БД" (с).


vas0
все зависит от того в каком у вас состоянии объект profile, если в persitent состоянии то dirty checking происходит автоматом и вам не нужно вызывать saveOrUpdate. Этот метод предназначен для перевода из состония detached в persistent.

dirty checking меня не устраивает.

expp

шо происходит тута
CustomerProfile profile = ...;

Тут я поднимаю из БД объект типа CustomerProfile, при помощи session.createQuery("...").uniqueResult();
expp

2. убери его нах

Ну не могу я убрать это :)
Смысл такой:
1. я загружаю объект.
2. изменяю в нём коллекцию (и другие параметры)
3. сохраняю объект.

При этом он мне так странно(см. выше) сохраняет коллекции.
26 июл 07, 16:06    [4440675]     Ответить | Цитировать Сообщить модератору
 Re: Hibernate обновление коллекции  [new]
expp
Member

Откуда: spb now
Сообщений: 1240
так чувак ты до конца меня достал ...

когда ты достал объект из сессии
автор
session.createQuery("...").uniqueResult();


теперь она думает о нём. тебе уже не надо. меняешь коллекцию. изменения попадут в базу при flushе по commit'у транзакции (jta). ты можешь принудительно его вызвать.

не надо вызывать
update()
для хибера это нечто иное чем ты вообразил.

чем тебе не приглянулся dirty check?

и учти что хибер-style сильно отличается от Oracle/SQL. оно тебе надо 7 мош ну его ?
26 июл 07, 16:34    [4440918]     Ответить | Цитировать Сообщить модератору
 Re: Hibernate обновление коллекции  [new]
Angel13
Member

Откуда: Киев
Сообщений: 156
expp

изменения попадут в базу при flushе по commit'у транзакции

Допустим.
Но коллекция попадёт в БД опять таки так:
сначала delete всех строк в таблице связей
а потом Insert их снова.
DEBUG[AbstractCollectionPersister.remove] done deleting collection
DEBUG[AbstractCollectionPersister.recreate] Inserting collection: 

Вот это проблема!

expp

и учти что хибер-style сильно отличается от Oracle/SQL. оно тебе надо 7 мош ну его ?

Производственная необходимость :(
26 июл 07, 16:45    [4441033]     Ответить | Цитировать Сообщить модератору
 Re: Hibernate обновление коллекции  [new]
Timm
Member

Откуда: Moscow, Ё-burg
Сообщений: 3729
Какая версия хибера?
не уверен, но он либо не умеет обновлять коллекции частично, либо научился делать это недавно.
могу ошибаться, я с ним не работал.
26 июл 07, 16:59    [4441202]     Ответить | Цитировать Сообщить модератору
 Re: Hibernate обновление коллекции  [new]
expp
Member

Откуда: spb now
Сообщений: 1240
ботва какаято .
показывай исходники сущностей, тест, лог .

не понял insert/delete sql в логе есть ?

и не надо ля ля всё он делает так что ... зашибись
26 июл 07, 17:09    [4441289]     Ответить | Цитировать Сообщить модератору
 Re: Hibernate обновление коллекции  [new]
Timm
Member

Откуда: Moscow, Ё-burg
Сообщений: 3729
expp
ботва какаято .
показывай исходники сущностей, тест, лог .

не понял insert/delete sql в логе есть ?

и не надо ля ля всё он делает так что ... зашибись

а польку сплясать могёт?
PS. невозможность обновить коллекцию может быть вызвана, к примеру, отсутствием PK на таблице-связке.
26 июл 07, 17:12    [4441321]     Ответить | Цитировать Сообщить модератору
 Re: Hibernate обновление коллекции  [new]
Angel13
Member

Откуда: Киев
Сообщений: 156
expp

показывай исходники сущностей, тест, лог .

не понял insert/delete sql в логе есть ?

Исходники сущностей в первом посте. Вырезка из Лога там же. delete/insert там есть :(

Timm

PS. невозможность обновить коллекцию может быть вызвана, к примеру, отсутствием PK на таблице-связке.

В приложении структура таблиц. PK на таблице связке есть (сделан как autoincrement поле). Но Хибернейт о нём, судя по всему не знает. Где ему это указать?

Hibernate 3.0

К сообщению приложен файл. Размер - 0Kb
26 июл 07, 17:35    [4441520]     Ответить | Цитировать Сообщить модератору
 Re: Hibernate обновление коллекции  [new]
Timm
Member

Откуда: Moscow, Ё-burg
Сообщений: 3729
м.б. @IndexColumn(name="interest_codes_id")?
26 июл 07, 18:21    [4441867]     Ответить | Цитировать Сообщить модератору
 Re: Hibernate обновление коллекции  [new]
expp
Member

Откуда: spb now
Сообщений: 1240
оочень странные байки...

варианты использовать Set и мапить ассоц таблицу руками.

завтра проверю...
26 июл 07, 19:07    [4442084]     Ответить | Цитировать Сообщить модератору
 Re: Hibernate обновление коллекции  [new]
expp
Member

Откуда: spb now
Сообщений: 1240
использование Setа мне помогло. объяснение
автор
Bags are the worst case....
27 июл 07, 10:01    [4443536]     Ответить | Цитировать Сообщить модератору
 Re: Hibernate обновление коллекции  [new]
Angel13
Member

Откуда: Киев
Сообщений: 156
Timm
@IndexColumn(name="interest_codes_id")


Помогло!! Спасибо!

Теперь только мне не понятна работа Hibernate с полем interest_codes_id. Он явно не использует Сиквенс. Надеюсь что он не делает max() +1.
27 июл 07, 12:16    [4444806]     Ответить | Цитировать Сообщить модератору
 Re: Hibernate обновление коллекции  [new]
Timm
Member

Откуда: Moscow, Ё-burg
Сообщений: 3729
Angel13
Теперь только мне не понятна работа Hibernate с полем interest_codes_id. Он явно не использует Сиквенс. Надеюсь что он не делает max() +1.

Ну, можно включить дебаг для statements+binds и поглядеть.
http://www.javalobby.org/java/forums/t44119.html
27 июл 07, 12:22    [4444852]     Ответить | Цитировать Сообщить модератору
 Re: Hibernate обновление коллекции  [new]
Angel13
Member

Откуда: Киев
Сообщений: 156
Оставляю информацию для потомков:

в таблице
create table interest_codes (
   interest_codes_id    serial not null,
   customer_profile_id  int8                 null,
   interest_dict_id     int8                 null,
   constraint interest_codes_id_pk primary key (interest_codes_id)
);

пришлось поменять PK с interest_codes_id на пару (customer_profile_id, interest_dict_id ), потому что interest_codes_id hibernate генерит уникальным только в рамках одного значения customer_profile_id.

Пример:

0;661;5
1;661;21
2;661;17
3;661;12
4;661;19
5;661;24
0;660;12
1;660;19
2;660;24
27 июл 07, 12:51    [4445137]     Ответить | Цитировать Сообщить модератору
 Re: Hibernate обновление коллекции  [new]
expp
Member

Откуда: spb now
Сообщений: 1240
@IndexColumn() определяет колонку в которой храниться индекс элементов списка. думаю это не совсем то чего следует хотеть

ManyToMany стоит мапить :

- Set ом с прямой стороны Collection c инверсной (та которая mappedBy)

- если же bag (Collection ) с обоих сторон (получаем полное удаление и вставку всей коллекции) то стоит использовать ColumnId. тем самым объявляя коллекцию idbag ом. ColumnId определяет первичный ключ для ассоциативной таблицы, как и хотел Анхел13.
работает это прикольно, например если для пары объектов разрываем такое отношение, а для пары вставляем - получаем только один update ассоциативной таблицы
7 авг 07, 11:36    [4488685]     Ответить | Цитировать Сообщить модератору
 Re: Hibernate обновление коллекции  [new]
expp
Member

Откуда: spb now
Сообщений: 1240
UPDATE

@CollectionId
7 авг 07, 11:53    [4488857]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: Hibernate обновление коллекции  [new]
SurvOrDie
Member

Откуда:
Сообщений: 6
expp
меня реально задрал этот антипаттерн: http://forum.hibernate.org/viewtopic.php?t=977710 https://www.sql.ru/forum/actualthread.aspx?tid=453741&hl=manytomany update delete insert

hiber и DAO очень разные вещи.

если тут
CustomerProfile profile = ...;
объект вытащили из сессии (или вставили)

то второй раз
dao.update(profile);
это делать не надо

Ооо, спасибо большое. А я то думаю, чё у меня за ошибка. )))
9 апр 19, 01:44    [21856597]     Ответить | Цитировать Сообщить модератору
 Re: Hibernate обновление коллекции  [new]
alex55555
Member

Откуда:
Сообщений: 1966
Angel13
При добавлении кода в коллекцию, и затем сохранения главного объекта
CustomerProfile profile = ...;		
profile.getInterestCodes().add(...);
dao.update(profile);

Здесь важно, как создаётся profile. Если это new, то всё логично - в нём нет старых связей и к нему добавляются новые, в итоге хибер удаляет старые и добавляет новые. Если же получение в транзакции от хибера - совсем другая песня. Так что надо показывать подробно, а не "как мне кажется".
9 апр 19, 11:48    [21856915]     Ответить | Цитировать Сообщить модератору
Все форумы / Java Ответить