【问题标题】:JPA EmptyResultDataAccessException handlingJPA EmptyResultDataAccessException 处理
【发布时间】:2017-01-07 02:26:53
【问题描述】:

我正在为一个大学项目编写一个简单的库 API。我有一个包含书籍的数据库,每本书都有自己的 ID。我正在使用 Spring Boot 来提供服务。我有一个扩展JpaRepository<Book, Long>BookRepository 和一个服务实现。

@Service
public class BookServiceImpl implements BookService{

   @Autowired
   private BookRepository bookRepository;

   @Async
   @Override
   public void delete (Long id){
       bookRepository.delete(id);
    }
}

稍后,REST 控制器处理请求:

@RestController
public class BookServiceController{

    @Autowired
    private BookService bookService;

    @RequestMapping(value="books/{id}", method = RequestMethod.DELETE)
    public ResponseEntity<Book> deleteBook (@PathVariable("id") Long id){
        bookService.delete(id);
        return new ResponseEntity<Book>(HttpStatus.OK);
    }
}

现在,如果我要删除不在数据库中的 Book,例如 ID 为 123,我会抛出 EmptyResultDataAccessException。

我的问题是,我如何以及在哪里处理异常,以及如何避免以这种方式投射 NullPointerException?

提前致谢。

【问题讨论】:

  • (1) 您是否有理由在存储库上分层单独的BookService? (2) 尽可能选择构造函数注入而不是字段注入。

标签: java spring rest spring-data spring-data-jpa


【解决方案1】:

DELETE 操作的情况下,您实际上不再返回实体;您只是在确认资源已消失。由于DELETE 是幂等的(您可以多次删除记录),因此无论记录是否存在,您都可以返回相同的状态码,或者如果未找到记录,则返回 404。您还可以简化处理程序方法:

@DeleteMapping("/books/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT) // because you deleted it
public void deleteBook(@PathVariable Long id) {
    try {
        bookService.delete(id); // or just use the repository directly
    } catch (EmptyResultDataAccessException ex) {
        // either do nothing to return a 204, or
        throw new NotFoundException();
    }
}

你有一个异常指示状态:

@ResponseStatus(HttpStatus.NOT_FOUND)
public class NotFoundException extends RuntimeException {}

EmptyResultDataAccessException 应该已经被注释为NOT_FOUND 的状态是合理的;这是一个潜在的增强请求。

【讨论】:

  • 我试过了,它仍然返回 EmptyResultDataAccessException。
  • 即使在使用此解决方案后,我仍然收到 EmptyResultDataAccessException
【解决方案2】:

避免EmptyResultDataAccessException 最优雅的方法是在您的Repository 接口中定义一个特定方法以通过您的id 字段删除。

假设您的 id 字段名为 bookId:

public interface BookRepository extends JpaRepository<Book, Long> {
    Long deleteByBookId(Long bookId);
}

这样就不会抛出异常了。

如果您的 id 字段简称为 id,我还没有测试过解决方案。

【讨论】:

  • 这种方法也应该被接受为正确答案。
猜你喜欢
  • 2017-03-07
  • 2015-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-04
  • 1970-01-01
  • 2018-10-14
  • 2011-09-26
相关资源
最近更新 更多