当我尝试更改@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();
知道差异是什么吗?
答案 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)。