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 只有保存方法,但它既可以插入也可以更新。
- 当您对 ID 为空的实体进行保存时,它会进行保存。
- 当您使用现有 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);
}
}
我有一个问题,已经好几个小时了,我一直在努力解决这个问题。
我必须使用 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 只有保存方法,但它既可以插入也可以更新。
- 当您对 ID 为空的实体进行保存时,它会进行保存。
- 当您使用现有 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);
}
}