hibernate:如何解决“从X到Y更改实例的标识符”?

org.hibernate.HibernateException: identifier of an instance of org.cometd.hibernate.User altered from 12 to 3 

实际上,我的user表是真的必须dynamic地改变它的值,我的Java应用程序是multithreading的。 任何想法如何解决它?

您是否在某处更改用户对象的主键值? 你不应该这样做。 检查您的主键映射是否正确。

您的映射XML文件或映射注释是什么样的?

在修改ID字段之前,您必须从会话中分离您的实体

在我的情况下,hbm.xml中的PK字段的types是“整数”,但在bean代码中是long

在我的具体情况下,这是由我的服务实现中的一个方法引起的,需要Spring @Transactional(readOnly = true)注解。 一旦我补充说,这个问题已经解决了。 不寻常的,但这只是一个select的声明。

在我的情况下,我解决了它将@Id字段types从long更改为Long。

在我的情况下,模板有一个错字,而不是检查是否等价(==)它使用了一个赋值equals(=)。

所以我改变了模板的逻辑:

 if (user1.id = user2.id) ... 

 if (user1.id == user2.id) ... 

现在一切都很好 所以,请检查您的意见!

在我的情况下,getter和setter名称与variables名称不同。

 private Long stockId; public Long getStockID() { return stockId; } public void setStockID(Long stockID) { this.stockId = stockID; } 

它应该在哪里

 public Long getStockId() { return stockId; } public void setStockId(Long stockID) { this.stockId = stockID; } 

确保在更改ID时不要多次尝试使用同一个用户对象。 换句话说,如果你在批处理types操作中做某事:

 User user = new User(); // Using the same one over and over, won't work List<Customer> customers = fetchCustomersFromSomeService(); for(Customer customer : customers) { // User user = new User(); <-- This would work, you get a new one each time user.setId(customer.getId()); user.setName(customer.getName()); saveUserToDB(user); } 

我也面对这个问题。

目标表是一个关系表,连接来自不同表的两个ID。 我在值组合上有一个UNIQUE约束,取代了PK。 当更新一个元组的值时,发生这个错误。

这就是表(MySQL)的样子:

 CREATE TABLE my_relation_table ( mrt_left_id BIGINT NOT NULL, mrt_right_id BIGINT NOT NULL, UNIQUE KEY uix_my_relation_table (mrt_left_id, mrt_right_id), FOREIGN KEY (mrt_left_id) REFERENCES left_table(lef_id), FOREIGN KEY (mrt_right_id) REFERENCES right_table(rig_id) ); 

RelationWithUnique实体的实体类看起来基本上是这样的:

 @Entity @IdClass(RelationWithUnique.class) @Table(name = "my_relation_table") public class RelationWithUnique implements Serializable { ... @Id @ManyToOne @JoinColumn(name = "mrt_left_id", referencedColumnName = "left_table.lef_id") private LeftTableEntity leftId; @Id @ManyToOne @JoinColumn(name = "mrt_right_id", referencedColumnName = "right_table.rig_id") private RightTableEntity rightId; ... 

我修好了

 // usually, we need to detach the object as we are updating the PK // (rightId being part of the UNIQUE constraint) => PK // but this would produce a duplicate entry, // therefore, we simply delete the old tuple and add the new one final RelationWithUnique newRelation = new RelationWithUnique(); newRelation.setLeftId(oldRelation.getLeftId()); newRelation.setRightId(rightId); // here, the value is updated actually entityManager.remove(oldRelation); entityManager.persist(newRelation); 

非常感谢PK的暗示,我只是错过了。

在我的情况,这是因为该属性是对象很长,但在映射XML int,这个例外应该更清楚

如果您使用的是Spring MVC或Spring Boot,请尽量避免: @ModelAttribute(“user”)在一个控制器中,而在其他控制器中则为model.addAttribute(“user”,userRepository.findOne(someId);

这种情况会产生这样的错误。

问题也可以在不同types的对象的PK(在你的情况下的“用户”),并键入你问冬眠得到session.get(type, id);

在我的情况下,错误是identifier of an instance of <skipped> was altered from 16 to 32 。 对象的PKtypes是Integer ,hibernate被要求为Longtypes。

这是一个古老的问题,但我要为我的特定问题(Spring Boot,使用Hibernate的JPA,SQL Server 2014)添加修补程序,因为它与此处包含的其他答案不完全匹配:

我有一个外键,例如my_id ='12345',但引用列中的值是my_id ='12345'。 它有一个额外的空间 ,冬眠不喜欢的结尾。 我删除了空间,修复了允许这个额外空间的部分代码,并且一切正常。