Spring数据问题-org.hibernate.HibernateException:{Entity}实例的标识符从1更改为2

时间:2019-01-21 16:15:15

标签: hibernate docker kubernetes spring-data-jpa

为实体(@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使用不同的图像

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

感谢您的咨询。

2 个答案:

答案 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))
    );

同时使用entityentityToUpdate的事实是一种代码味道,这可能与使用不需要的lambda有关。

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

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

    entity.setIsConfirmed(true);
    entity.setVersionTs(getCurrentTime());
    return getRepository().save(entity);
}

答案 1 :(得分:0)

主要问题在mapper中。代替父代替换,它仅更改获取的父代的ID。然后,我们替换父对象,但获取的父对象仍保留在缓存中(具有新的ID),并在一段时间后尝试将此刷新刷新到数据库中,然后进入休眠状态。