Hibernate, изменить идентификатор / первичный ключ - PullRequest
18 голосов
/ 09 апреля 2009

Я получаю следующее исключение при попытке изменить @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

Вместо использования более ОО подхода:

beginTransaction();
T e = session.load(...);
e.setName(newName);
session.saveOrUdate(e);
commit();

Есть идеи, что такое разница?

Ответы [ 4 ]

21 голосов
/ 07 февраля 2010

На самом деле, согласно спецификации JPA запрещено менять первичный ключ:

Приложение не должно изменять значение первичного ключа [8]. Поведение не определено, если это происходит. [9]

(из спецификации EJB 3 персистентности (JPA), п. 2.1.4)

11 голосов
/ 10 апреля 2009

Я не могу представить, почему вы хотите это сделать. Совсем. Зачем вам менять личность лица? Вам также необходимо обновить все внешние ключи в других таблицах, которые на него указывают. Похоже на боль, без выгоды. Возможно, вам лучше сделать это «бизнес-ключом» (обычное свойство) и использовать более постоянный суррогатный ключ. У меня такое чувство, что ты все делаешь неправильно, но если ты настаиваешь ...

По сути, вы создаете нового Клиента и удаляете старого, и именно так я бы это сделал в 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, и в любом случае вы рискуете иметь параллельные процессы, у которых уже есть экземпляр «старого» клиента, что может привести к некоторому ошибки.

4 голосов
/ 12 июня 2009

Мой друг, вы правы. Нет способа (или я не знаю способа) изменить первичный ключ без использования операторов HQL. Это не нормально, но это правда.

3 голосов
/ 25 марта 2011

Это не решение, так как я считаю, что на него уже был дан ответ.

Тем не менее, я хотел предложить то, что я считал допустимым сценарием для желания сделать это. (Комментарии приветствуются)

1) Таблица USER_ELECTRONICS имеет много ко многим с таблицей ELECTRONICS_DEF

2) Этот список «многие ко многим» является упорядоченным. Каждый USER_ELECTRONIC_ID имеет приоритетный список ELECTRONICS_DEF_IDs. Например, у меня есть 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. ПРИОРИТЕТ - Композитный ФК.

3) Когда я хочу изменить таблицу с точки зрения моих предпочтений (мой новый IPad2 занимает первое место в списке, а iPad переместился на # 4), мне нужно обновить часть составного FK (PRIORITY).

...