如何解决CrudRepository - Hibernate - 用手动设置的 id 覆盖现有模型
我必须使用 CrudRepository 和 Hibernate 在数据库中保存一个手动设置 ID 的模型。
但是手动设置的 id 总是被忽略。
有没有可能,强制
CrudRepository.save(Model m)
使用 UPDATE 持久化给定的模型?
查询总是产生 INSERT 语句,而不使用 id。
我必须手动执行此操作的原因是,标识符不是数据库 ID - 它是在外部生成的作为 UUID 的 ID,它在具有此模型条目的多个数据库中是唯一的。该模型通过 hazelcast-cluster 作为序列化对象共享。
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 方法,但它同时用于插入和更新。
- 当您对 id 为空的实体进行保存时,它会进行保存。
- 当您使用现有 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 举报,一经查实,本站将立刻删除。