У меня есть код для удаления рецепта из моей базы данных mongoDB:
@RequestMapping(value = "/recipe/{id}", method = RequestMethod.DELETE)
public String deleteSingleRecipe(@PathVariable("id") String recipeId) {
try {
repository.deleteById(recipeId);
return "Deleted RECIPE success";
} catch (Exception ex) {
return ex.toString();
}
}
Это может успешно удалить рецепт на основе идентификатора. Однако я не уверен, как отловить такие случаи, когда рецепт даже не существует или если удаление не удалось.
С JavaScript/Node это было очень просто, потому что я мог передать функцию обратного вызова, и в зависимости от того, был ли результат/ошибка нулевым, я мог определить успех запроса и продолжить. Я совершенно не понимаю, как это сделать в Java/Spring.
Когда я попытался удалить рецепт во второй раз, я все равно получил сообщение «удален рецепт успешно».




Вы можете добавить проверку перед использованием existsById
boolean isFound = repository.existsById(recipeId);
Returns whether an entity with the given id exists.
@Birdman, если вы будете использовать jdbcTemplate, он вернет количество обновленных строк, см. docs.spring.io/spring/docs/current/javadoc-api/org/…, см. также stackoverflow.com/questions/36021525/….
Ну, в этом случае не jdbcTemplate, а MongoTemplate удалит методы, которые возвращают DeleteResult
Как предложил @JEY, есть также методы удаления MongoTemplate как docs.spring.io/spring-data/mongodb/docs/current/api/org/…
Это было полезно для ответа на мой комментарий: поскольку MongoRepsitory реализует CredRepository, здесь была некоторая информация о save (): baeldung.com/spring-data-crud-repository-save «Метод save () возвращает сохраненный объект, включая обновленное поле идентификатора».
Попробуйте добавить новый метод в интерфейс репозитория, подобный этому
@Modifying
@Query("DELETE FROM MY_TABLE WHERE ID = ?1")
default boolean deleteById(IdPrimitiveType id){
return true;
}
Надеюсь, поможет
Если вы проверите интерфейс JPARepository, вы получите
/**
* Deletes the entity with the given id.
*
* @param id must not be {@literal null}.
* @throws IllegalArgumentException in case the given {@code id} is {@literal null}
*/
void deleteById(ID id);
/**
* Deletes a given entity.
*
* @param entity
* @throws IllegalArgumentException in case the given entity is {@literal null}.
*/
void delete(T entity);
поэтому в соответствии с вашим требованием он не будет генерировать никаких исключений, если данный идентификатор не существует в БД.
для этого вы можете использовать boolean isFound = repository.existsById(recipeId);, и если isFound верно, вы можете удалить его. и если isFound ложно, вы можете выдать исключение.
второй способ, вы можете проверить
public class SimpleJpaRepository<T, ID> implements JpaRepository<T, ID>, JpaSpecificationExecutor<T>
этот класс содержит метод deleteById. и этот метод выдаст исключение, если id не существует в БД.
/*
* (non-Javadoc)
* @see org.springframework.data.repository.CrudRepository#delete(java.io.Serializable)
*/
@Transactional
public void deleteById(ID id) {
Assert.notNull(id, ID_MUST_NOT_BE_NULL);
delete(findById(id).orElseThrow(() -> new EmptyResultDataAccessException(
String.format("No %s entity with id %s exists!", entityInformation.getJavaType(), id), 1)));
}
Об этом сообщили Spring как об ошибке (которая все еще открыта): https://jira.spring.io/browse/DATAMONGO-1997?jql=text%20~%20%22deleteById%22
Проверка того, существует ли он до или после, не была для нас решением, поскольку она чувствительна к состоянию гонки. Лучший и более эффективный обходной путь, который мы нашли, был предложен @SandOfTime: в вашем интерфейсе MongoRepository добавьте:
@DeleteQuery("{_id:?0}")
Long deleteByIdReturningDeletedCount(String id);
У меня также было подобное требование, но мой случай немного отличается. Сначала я скажу свое требование: мне нужно добавить пользователя, если имя пользователя не существует. Итак, в репозитории есть встроенный метод поиска имени пользователя.
Usermodel findByUsername(String username);
Итак, на уровне контроллера я реализовал следующее.
public String signUp(@RequestBody Usermodel user) {
if (userRepository.findByUsername(user.getUsername())==null) {
userRepository.save(user);
return "Success";
}
else{
return "Username Already Exsist";
}
}
Я думаю, что для вашего случая это также может быть применено. Нужно проверить recipeId, а затем вы можете выполнить удаление.
Начиная с Spring Data JPA (>=1.7.x), мы можем использовать производный запрос delete или remove. Он возвращает количество удаленных объектов или количество удаленных объектов.
Используя его, вы можете обновить свой код как:
public interface RecipetRepository extends CrudRepository<Reciepe, Long> {
long deleteById(String id);
}
и мы можем создать исключение, если объект не существует.
@RequestMapping(value = "/recipe/{id}", method = RequestMethod.DELETE)
public String deleteSingleRecipe(@PathVariable("id") String recipeId) {
long numberOfRecipiesDeleted;
try {
numberOfRecipiesDeleted = repository.deleteById(recipeId);
} catch (DataAccessException ex) {
return ex.toString();
}
if (numberOfRecipiesDeleted == 0){
throw new ReciepeNotFoundException();
}
return "Deleted RECIPE success";
}
Я полагаю, что это приемлемо, но также требует дополнительного чтения базы данных. Кроме того, я искал более «обобщенное» решение, чем просто решить мою 1 проблему. Например, что, если я добавлю новый элемент в БД? Является ли единственный способ проверить, действительно ли он был успешным, чтобы впоследствии проверить, существует ли он в базе данных? (Кроме того, как мне получить идентификатор для проверки этого объекта в базе данных?) Отсутствие возвращаемых значений или данных расстраивает.