我正在为大学项目编写一个简单的库API。我有一个带书籍的数据库,每个都有自己的ID。我正在使用Spring Boot来提供服务。我有BookRepository
扩展JpaRepository<Book, Long>
和服务实现。
@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?
提前致谢。
答案 0 :(得分: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
,这似乎是合理的。这是一个潜在的增强请求。
答案 1 :(得分:1)
避免 EmptyResultDataAccessException
的最优雅方法是在您的 Repository
接口中定义特定方法以通过您的 id 字段进行删除。
假设您的 id 字段名为 bookId:
public interface BookRepository extends JpaRepository<Book, Long> {
Long deleteByBookId(Long bookId);
}
这样就不会抛出异常了。
如果您的 id 字段被简单地称为 id,我还没有测试过该解决方案。