Hibernate,alter identifier / primary key

时间:2009-04-09 14:20:41

标签: hibernate primary-key

当我尝试更改@ID中的@Entity时,我收到以下异常。

identifier of an instance of com.google.search.pagerank.ItemEntity was altered from 1 to 2.

我知道我正在改变表格中的主键。我正在使用JPA-annotations。

我通过使用这个单一的HQL查询解决了这个问题:update Table set name=:newName where name=:oldName

而不是使用更多OO方法:

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

知道差异是什么吗?

4 个答案:

答案 0 :(得分:21)

实际上,根据JPA规范,禁止更改主键:

  

应用程序不得更改主键的值[8]。如果发生这种情况,行为是不确定的。[9]

(来自EJB 3持久性(JPA)规范,第2.1.4段)

答案 1 :(得分:11)

我无法想象你为什么要那样做。完全没有。你为什么要改变一个实体的身份?您还需要更新指向它的其他表中的所有外键。看起来像是痛苦,没有收获。您可能最好将其作为“业务密钥”(普通财产)并使用更长久的代理密钥。我有一种感觉,你说这一切都错了,但如果你坚持......

基本上你正在做的是创建一个新客户并删除旧客户,这就是我在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 :(得分:4)

我的朋友, 你是对的。没有办法(或者我不知道一种方法)在不使用HQL语句的情况下更改主键。这不正常,但确实如此。

答案 3 :(得分:3)

这不是一个解决方案,因为我相信上面已经回答过。

但是,我想提供我认为有用的方案,希望这样做。 (欢迎评论)

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),我需要更新部分复合FK(PRIORITY)。