CrudRepository - Hibernate - 使用手动设置 ID 覆盖现有模型

CrudRepository - Hibernate - Overwrite existing model with manual set id

我有一个问题,已经好几个小时了,我一直在努力解决这个问题。

我必须使用 CrudRepository 和 Hibernate 在数据库中保存带有手动设置 ID 的模型。

但是总是忽略手动设置的id。

有没有可能,强制

CrudRepository.save(Model m)

要使用 UPDATE 保留给定模型?

查询总是产生 INSERT 语句,而不使用 id。

我必须手动执行此操作的原因是,标识符不是数据库 ID - 它是在外部作为 UUID 生成的 ID,它在具有此模型条目的多个数据库中是唯一的。此模型通过 hazelcast-cluster 作为序列化对象共享。

下面举个例子: 数据库已包含 ID 为 1 的模型条目:

id    identifier_field_with_unique_constraint     a_changing_number
1     THIS_IS_THE_UNIQUE_STRING                   10

现在我需要更新它。我创建了一个新的模型版本

Model m = new Model();
m.setIdentifierFieldWithUniqueConstraint(THIS_IS_THE_UNIQUE_STRING);
m.setAChangingNumberField(20);
saveMe(m);

void saveMe(Model m) {
    Optional<Model> presentModalOpt = modelCrudRepo.findByIdentField(THIS_IS_THE_UNIQUE_STRING)
    if(presentModalOpt.isPresent()) {
        // The unique value in my identifier field exists in the database already
        // so use that id for the new model, so it will be overwritten
        m.setId(modalOpt.get().getId());
    } else {
        m.setId(null);
    }
    // This call will now do an INSERT, instead of UPDATE, 
    // even though the id is set in the model AND the id exists in the database!
    modelCrudRepo.save(m);
    // ConstraintViolationException for the unique identifier field.
    // It would be a duplicate now, which is not allowed, because it uses INSERT instead of UPDATE
}

id字段带有@Id和@GeneratedValue注解(针对id为null的情况,需要生成id)

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)

我什至尝试将此字段仅更改为不带@GeneratedValue 的@Id 字段,并始终自行生成ID。它没有效果,它总是使用 INSERT 语句,从不使用 UPDATE。

我做错了什么?

除了 id 之外,CrudRepository 是否还有另一个标识符将模型声明为现有模型?

很高兴能得到任何帮助。

CrudRepository 只有保存方法,但它既可以插入也可以更新。

  1. 当您对 ID 为空的实体进行保存时,它会进行保存。
  2. 当您使用现有 ID 保存实体时,它会进行更新 这意味着在您使用 findById 并更改之后 对象中的某些内容,您可以调用保存此对象并将其保存 实际上会进行更新,因为在 findById 之后你会得到一个对象 使用您的数据库中存在的填充 ID。

在您的情况下,您正在根据字段获取记录 (unique) 但是 记录仅在模型对象具有现有主键值时才会更新

在你的代码中应该有 presentModalOpt 而不是 modalOpt

void saveMe(Model m) {
    Optional<Model> presentModalOpt = modelCrudRepo.findByIdentField(THIS_IS_THE_UNIQUE_STRING)
    if(presentModalOpt.isPresent()) {  // should be presentModalOpt instead of modalOpt
 
    } else {
        m.setId(null);
    }
    modelCrudRepo.save(m);
    
}

查看默认实现-

/*
 * (non-Javadoc)
 * @see org.springframework.data.repository.CrudRepository#save(java.lang.Object)
 */
@Transactional
public <S extends T> S save(S entity) {

     if (entityInformation.isNew(entity)) {
          em.persist(entity);
          return entity;
     } else {
          return em.merge(entity);
     }
}