java - CrudRepository - Hibernate - 用手动设置 id 覆盖现有模型
问题描述
我有一个问题,从现在开始我一直在尝试解决。
我必须使用 CrudRepository 和 Hibernate 在数据库中保存具有手动设置 ID 的模型。
但是id的手动设置总是被忽略。
是否有可能,强制
CrudRepository.save(模型 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 只有 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);
}
}
推荐阅读
- angular - 尝试从 Cloud Storage 获取 downloadURL 时出现多个 Promise 的问题
- javascript - 在 Safari 中从括号中打开预览
- java - 用java中的反射检查一个字段是真还是假
- recursion - 如何在 PROLOG 中找到两个站点之间的路线
- asp.net-mvc - 服务权限被拒绝 - Fedora 31
- java - boot_completed 不适用于 Android 10 Q API 级别 29
- python - 在熊猫中编辑日期以仅按列显示年份
- laravel - 无法在刀片模板中显示图像
- python - 为什么我的 VScode 中的函数声明不匹配?
- r - 使用 mutate 和 case_when (R) 通过多个条件创建新变量的函数