JPA EmptyResultDataAccessException 处理

Flo*_*opn 8 java rest spring spring-data spring-data-jpa

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

@Service
public class BookServiceImpl implements BookService{

   @Autowired
   private BookRepository bookRepository;

   @Async
   @Override
   public void delete (Long id){
       bookRepository.delete(id);
    }
}
Run Code Online (Sandbox Code Playgroud)

稍后,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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

提前致谢。

And*_*rez 6

避免这种情况的最优雅的方法EmptyResultDataAccessException是在界面中定义一个特定的方法Repository来通过 id 字段删除。

假设您的 id 字段名为 bookId:

public interface BookRepository extends JpaRepository<Book, Long> {
    Long deleteByBookId(Long bookId);
}
Run Code Online (Sandbox Code Playgroud)

这样就不会抛出异常。

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


chr*_*ke- 4

在操作的情况下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();
    }
}
Run Code Online (Sandbox Code Playgroud)

其中有一个指示状态的异常:

@ResponseStatus(HttpStatus.NOT_FOUND)
public class NotFoundException extends RuntimeException {}
Run Code Online (Sandbox Code Playgroud)

似乎EmptyResultDataAccessException应该已经用状态注释NOT_FOUND; 这是一个潜在的增强请求。