微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

CrudRepository - Hibernate - 用手动设置的 id 覆盖现有模型

如何解决CrudRepository - Hibernate - 用手动设置的 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。

我做错了什么?

CrudRepository 是否有另一个标识符将模型声明为现有模型,而不是 id?

很高兴为您提供帮助。

解决方法

CrudRepository 只有 save 方法,但它同时用于插入和更新。

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

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

在您的代码中应该有 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);
     }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。