Hibernate:如何修复“从X更改为Y的实例的标识符”?
-
10-10-2019 - |
题
org.hibernate.HibernateException: identifier of an instance
of org.cometd.hibernate.User altered from 12 to 3
实际上,我的 user
表确实必须动态地更改其值,我的Java应用程序是多线程。有什么想法如何解决?
解决方案
您是否正在更改某个地方用户对象的主要密钥值?你不应该那样做。检查主键的映射是否正确。
您的映射XML文件或映射注释是什么样的?
其他提示
您必须在修改其ID字段之前将您的实体分离为会话
就我而 long
.
就我而言,我解决了它将@ID字段类型从长时间更改为长。
在我的情况下,Geters和Setter名称与变量名不同。
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;
}
在我的特殊情况下,这是由我的服务实施中的一种方法引起的,需要弹簧 @Transactional(readOnly = true)
注解。一旦我补充说,问题就解决了。不过,不寻常,这只是一个精选陈述。
就我而言,模板具有错别字,因此而不是检查等效性(==),而是使用分配等价(=)。
因此,我从:
if (user1.id = user2.id) ...
至
if (user1.id == user2.id) ...
现在一切都很好。因此,还要检查您的观点!
在更改ID时,请确保您不会尝试多次使用相同的用户对象。换句话说,如果您在批处理类型操作中做某事:
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。我对价值组合有独特的约束,取代了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的提示,我只是错过了。
问题也可以在不同类型的对象的PK(在您的情况下使用),然后键入您要求Hibernate获取 session.get(type, id);
.
在我的情况下,错误是 identifier of an instance of <skipped> was altered from 16 to 32
. 。对象的PK类型是 Integer
, ,冬眠被要求 Long
类型。
就我而言,这是因为该属性很长,但在映射XML中int,此例外应该更清楚
如果您使用的是Spring MVC或Spring Boot尝试避免:@modelattribute(“用户”) 在一个反对者和其他控制器中model.addattribute(“用户”,userrepository.findone(someid);
这种情况可能会产生这种错误。
这是一个古老的问题,但是我将添加我的特定问题的修复程序(Spring Boot,JPA使用Hibernate,SQL Server 2014),因为它与此处包含的其他答案不完全匹配:
我有一个外键,例如my_id ='12345',但是引用列中的值是my_id ='12345'。它有一个 额外的空间 在冬眠的最后不喜欢。我删除了空间,修复了允许此额外空间的代码部分,一切正常。
面对同样的问题。我在2个豆之间进行了调查。在bean中,AI将变量类型定义为整数,而Bean BI则定义了相同的变量。我将它们都更改为整数。这解决了我的问题。
这是您的更新方法中的问题。在保存更改之前,只需实例新用户,您就可以了。如果您使用DTO和实体类之间的映射,则在映射之前进行映射。
我也有这个错误。我有用户对象,试图更改其位置,位置是用户表中的FK。我解决了这个问题
@Transactional
public void update(User input) throws Exception {
User userDB = userRepository.findById(input.getUserId()).orElse(null);
userDB.setLocation(new Location());
userMapper.updateEntityFromDto(input, userDB);
User user= userRepository.save(userDB);
}
我通过实现依赖对象的新实例来解决此问题。例如
instanceA.setInstanceB(new InstanceB());
instanceA.setInstanceB(YOUR NEW VALUE);