1

我在更改实体的父级(@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);
    }

Spring boot 版本 - 2.1.2 Hibernate 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 尝试了不同的图像

有人可以建议一些解决方案吗?

谢谢指教。

4

2 回答 2

1

主要问题是在映射器中。而不是父级替换它,只更改获取的父级的 id。然后我们替换父级,但获取的父级仍保留在缓存中(具有新 id),一段时间后休眠尝试将此更改刷新到数据库中。

于 2019-01-23T13:25:26.667 回答
0

首先,updateEntity使用冗余的 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))
    );

您同时使用entityentityToUpdate是一种代码气味,这可能与使用也不需要的 lambdas 有关。

因此,您可能可以将所有代码简化为:

@Transactional
@Override
public Optional<EntityT> update(EntityT entity) {

    entity.setIsConfirmed(true);
    entity.setVersionTs(getCurrentTime());
    return getRepository().save(entity);
}
于 2019-01-21T16:29:34.033 回答