为实体(@OneToMany关系)更改父级时遇到此异常。
实体父级更新-org.hibernate.HibernateException:的标识符 {Entity}的实例从1更改为2
发生此异常,仅在一段时间后才能为在Kubernetes中运行的服务重现。我的意思是,它并不是从容器寿命的开始就复制出来的,并且一定数量的更新已成功完成。
对实体进行更新的方法如下:
@Transactional
@Override
public Optional<EntityT> update(EntityT entity) {
entity.setIsConfirmed(true);
return getRepository().findById(entity.getId())
.map(entityToUpdate -> updateEntity(entity, entityToUpdate));
}
private EntityT updateEntity(EntityT entity, EntityT entityToUpdate) {
modelMapper.map(entity, entityToUpdate);
getParentRepository().ifPresent(parentRepository ->
entity.getParent().ifPresent(parentEntity ->
parentRepository.findById(parentEntity.getId()).ifPresent(entityToUpdate::setParent))
);
entityToUpdate.setVersionTs(getCurrentTime());
return getRepository().save(entityToUpdate);
}
春季启动版本-2.1.2休眠5.3.7也尝试5.4.1-相同的结果。
还将spring jpa属性设置为
spring:
jpa:
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
generate-ddl: true
hibernate:
ddl-auto: update
properties:
hibernate:
jdbc:
batch_size: 100
flushMode: "ALWAYS"
order_inserts: true
order_updates: true
还尝试对容器open-jdk8 / oracle-jdk8使用不同的图像
有人可以建议一些解决方案吗?
感谢您的咨询。
答案 0 :(得分:0)
首先,updateEntity
使用redundant save-anti-pattern:
private EntityT updateEntity(EntityT entity, EntityT entityToUpdate) {
modelMapper.map(entity, entityToUpdate);
getParentRepository().ifPresent(parentRepository ->
entity.getParent().ifPresent(parentEntity ->
parentRepository.findById(parentEntity.getId()).ifPresent(entityToUpdate::setParent))
);
entityToUpdate.setVersionTs(getCurrentTime());
return getRepository().save(entityToUpdate);
}
第二,这部分不需要:
getParentRepository().ifPresent(parentRepository ->
entity.getParent().ifPresent(parentEntity ->
parentRepository.findById(parentEntity.getId()).ifPresent(entityToUpdate::setParent))
);
同时使用entity
和entityToUpdate
的事实是一种代码味道,这可能与使用不需要的lambda有关。
因此,您可以将所有代码简化为:
@Transactional
@Override
public Optional<EntityT> update(EntityT entity) {
entity.setIsConfirmed(true);
entity.setVersionTs(getCurrentTime());
return getRepository().save(entity);
}
答案 1 :(得分:0)
主要问题在mapper中。代替父代替换,它仅更改获取的父代的ID。然后,我们替换父对象,但获取的父对象仍保留在缓存中(具有新的ID),并在一段时间后尝试将此刷新刷新到数据库中,然后进入休眠状态。