【问题标题】:How to check for success/failure in Java Spring database queries?如何检查 Java Spring 数据库查询中的成功/失败?
【发布时间】:2019-04-08 06:14:22
【问题描述】:

我有一些代码可以从我的 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();
    }
}

这可以成功删除基于 ID 的配方。但是,我不确定如何捕捉配方甚至不存在或删除失败等情况。

使用 JavaScript/Node 这非常简单,因为我可以传递一个回调函数,取决于结果/错误是否为空,我可以确定查询是否成功并继续。我很迷茫如何在 Java/Spring 中做到这一点。

当我第二次尝试删除食谱时,我仍然得到“删除食谱成功”。

【问题讨论】:

    标签: java spring mongodb sql-delete


    【解决方案1】:

    如果您检查 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);
    

    所以根据您的要求,如果 DB 中不存在给定的 id,它不会抛出任何异常。

    为此,您可以使用boolean isFound = repository.existsById(recipeId);,如果isFound 为真,您可以将其删除。如果isFound 为假,则可以抛出异常。

    第二种方法是你可以检查

      public class SimpleJpaRepository<T, ID> implements JpaRepository<T, ID>, JpaSpecificationExecutor<T>
    

    这个类包含deleteById 方法。如果 id 在 DB 中不存在,此方法将抛出异常。

    /*
         * (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)));
        }
    

    【讨论】:

      【解决方案2】:

      您可以在使用existsById之前添加检查

      boolean isFound = repository.existsById(recipeId);
      

      返回具有给定 id 的实体是否存在。

      【讨论】:

      • 我想这是可以接受的,但也需要额外读取数据库。此外,我正在寻找更多的“通用”解决方案,而不仅仅是解决我的 1 个问题。例如,如果我向数据库添加新项目怎么办?检查它是否成功的唯一方法是事后检查它是否存在于数据库中? (此时我如何获取 ID 以检查数据库中的该对象?)缺少返回值或数据令人沮丧。
      • @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() 方法返回保存的实体,包括更新的 id 字段。”
      【解决方案3】:

      尝试像这样向存储库接口添加新方法

      @Modifying
      @Query("DELETE FROM MY_TABLE WHERE ID = ?1")
      default boolean deleteById(IdPrimitiveType id){
        return true;
       }
      

      希望对你有帮助

      【讨论】:

        【解决方案4】:

        已将其作为错误报告给 Spring(仍处于打开状态):https://jira.spring.io/browse/DATAMONGO-1997?jql=text%20~%20%22deleteById%22

        检查它是否存在之前或之后不是我们的解决方案,因为它对竞争条件很敏感。我们发现的最佳和更有效的解决方法是 @SandOfTime 建议的:在您的 MongoRepository 界面中,添加:

        @DeleteQuery("{_id:?0}")
        Long deleteByIdReturningDeletedCount(String id);
        

        【讨论】:

          【解决方案5】:

          我也有类似的要求,但我的情况略有不同。首先我会告诉我的要求,如果用户名不存在,我需要添加一个用户。所以在 Repository 中有一个内置的方法来查找用户名。

          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,然后才能执行删除。

          【讨论】:

            【解决方案6】:

            从 Spring Data JPA (>=1.7.x) 开始,我们可以使用派生的 deleteremove 查询。它返回删除的实体数量或所有实体都被删除的数量。

            使用它,您可以将代码更新为:

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-06-04
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多