Hibernate, идентификатор изменения/первичный ключ
Я получаю следующее исключение, когда пытаюсь изменить свой @ID
в @Entity
.
identifier of an instance of com.google.search.pagerank.ItemEntity was altered from 1 to 2.
Я знаю, что я изменяю первичный ключ в своей таблице. Я использую аннотации JPA.
Я решил это, используя этот единственный запрос HQL: update Table set name=:newName where name=:oldName
Вместо использования более OO-подхода:
beginTransaction();
T e = session.load(...);
e.setName(newName);
session.saveOrUdate(e);
commit();
Любая идея в том, что такое diff?
Ответы
Ответ 1
Я не могу представить, почему вы хотите это сделать. Вообще. Почему вы изменили бы идентификатор сущности? Вам также необходимо обновить все внешние ключи в других таблицах, которые указывают на него. Кажется, боль, без усиления. Вероятно, вам лучше сделать это "бизнес-ключ" (простое свойство) и использовать более постоянный ключ суррогата. У меня такое чувство, что вы все это делаете неправильно, но если вы настаиваете...
По сути дела, вы создаете нового Клиента и удаляете старый, и как я это делаю в Hibernate.
[псевдокод]
Begin Transaction
// create new customer from old
newC = Session.Load<Customer>(42)
Session.Evict(newC)
newC.Id = 1492
Session.Save(newC)
// update other relationships to point to newC
// ....
// delete old customer
oldC = Session.Load<Customer>(42)
Session.Delete(oldC)
Commit Transaction
Тем не менее, вам, вероятно, лучше всего делать это за один раз в простой транзакции SQL, и в любом случае вы рискуете иметь параллельные процессы, у которых уже есть экземпляр "старого" клиента, что может вызвать некоторые ошибки.
Ответ 2
Собственно, согласно спецификации JPA, запрещено изменять первичный ключ:
Приложение не должно изменять значение первичного ключа [8]. Поведение undefined, если это происходит. [9]
(из спецификации сохранения EJB 3 (JPA), пункт 2.1.4)
Ответ 3
Мой друг,
Ты прав. Нет способа (или я не знаю способа) изменить первичный ключ без использования инструкций HQL. Это не нормально, но это правда.
Ответ 4
Это не решение, так как я считаю, что был дан ответ выше.
Однако я хотел предложить то, что, по моему мнению, было правильным сценарием для этого. (Комментарии приветствуются)
1) Таблица USER_ELECTRONICS имеет много-ко-многим с таблицей ELECTRONICS_DEF
2) Это много-ко многим - упорядоченный список. Каждый USER_ELECTRONIC_ID имеет приоритетный список ELECTRONICS_DEF_ID. Например, у меня есть IPhone, IPad, сотовый телефон, и я оцениваю их по порядку, насколько они мне нравятся. Для этого у меня есть таблица USER_ELEC_PRIORITY_MAP, которая выглядит так:
USER_ELEC_ID
ELEC_DEF_ID
PRIORITY
1
IPAD
1
1
IPHONE
2
1
CELL
3
USER_ELEC_ID, а ELEC_DEF_ID - PFK. ПРИОРИТЕТ - это композитный FK.
3) Когда я хочу переупорядочить таблицу в соответствии с моими предпочтениями (мой новый IPad2 находится сверху в списке, а iPad переходит на # 4), мне нужно обновить часть Composite FK (ПРИОРИТЕТ).