Как проверить успех/неудача в запросах к базе данных Java Spring?

У меня есть код для удаления рецепта из моей базы данных 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.

Когда я попытался удалить рецепт во второй раз, я все равно получил сообщение «удален рецепт успешно».

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
0
6 301
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

Вы можете добавить проверку перед использованием existsById

boolean isFound = repository.existsById(recipeId);

Returns whether an entity with the given id exists.

Я полагаю, что это приемлемо, но также требует дополнительного чтения базы данных. Кроме того, я искал более «обобщенное» решение, чем просто решить мою 1 проблему. Например, что, если я добавлю новый элемент в БД? Является ли единственный способ проверить, действительно ли он был успешным, чтобы впоследствии проверить, существует ли он в базе данных? (Кроме того, как мне получить идентификатор для проверки этого объекта в базе данных?) Отсутствие возвращаемых значений или данных расстраивает.

Birdman 08.04.2019 08:37

@Birdman, если вы будете использовать jdbcTemplate, он вернет количество обновленных строк, см. docs.spring.io/spring/docs/current/javadoc-api/org/…, см. также stackoverflow.com/questions/36021525/….

user7294900 08.04.2019 08:41

Ну, в этом случае не jdbcTemplate, а MongoTemplate удалит методы, которые возвращают DeleteResult

JEY 08.04.2019 08:44

Как предложил @JEY, есть также методы удаления MongoTemplate как docs.spring.io/spring-data/mongodb/docs/current/api/org/…

user7294900 08.04.2019 08:48

Это было полезно для ответа на мой комментарий: поскольку MongoRepsitory реализует CredRepository, здесь была некоторая информация о save (): baeldung.com/spring-data-crud-repository-save «Метод save () возвращает сохраненный объект, включая обновленное поле идентификатора».

Birdman 08.04.2019 09:55

Попробуйте добавить новый метод в интерфейс репозитория, подобный этому

@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";
}

Другие вопросы по теме