Spring Data JPA - 如何实现正确的异常处理?

Luk*_*Luk 5 java hibernate spring-data-jpa spring-boot

我正在使用 Spring Data JPA 来处理数据库调用。为此,我创建了:

  1. EmployeeRepository 接口,它扩展了JpaRepository<Employee, Long>

  2. 一个 EmployeeService,它定义了三个方法:

     Employee saveEmployee(Employee employee);
     Optional<Employee> getEmployee(Long id);
     Long deleteEmployee(Long id);
    
    Run Code Online (Sandbox Code Playgroud)
  3. EmployeeService 的实现:

     @Override
     public Employee saveEmployee(Employee employee) {
         return employeeRepository.save(employee);
     }
    
     @Override
     public Optional<Employee> getEmployee(Long id) {
         return employeeRepository.findEmployeeById(id);
     }
    
     @Override
     public Long deleteEmployee(Long id) {
         employeeRepository.deleteById(id);
         return id;
     } 
    
    Run Code Online (Sandbox Code Playgroud)

问题如下:

get 方法工作正常并且可以返回一个可选值。另一方面,保存方法不能返回可选值。显然,JpaRepository 在调用 save() 时返回已保存对象的实例。我宁愿返回一个可选值,因为在保存员工时可能会出现问题,在这种情况下,我想抛出一个错误 - 即每当可选值不存在时,我就会抛出一个错误。

删除操作也是如此:例如,如果我要求删除一名员工并传入一个不存在的 id,该怎么办?我想捕获此错误,然后仅在删除操作成功时返回传入的 id。为此我必须捕获哪个错误?谁可以给我解释一下这个?

===================================================

更新:

  • 我通过在调用 `deleteById(id); 之前检查给定的员工 ID 是否存在,解决了删除调用的问题。如果不存在,服务返回 null,如果存在,则返回 id。控制器看起来像这样:

      @DeleteMapping("/{id}")
      public ResponseEntity<Long> deleteEmployee(@PathVariable Long id) {
          Long deletedEmployeeId = employeeService.deleteEmployee(id);
          if (deletedEmployeeId != null) {
              return ResponseEntity.ok(deletedEmployeeId);
      } else {
          return ResponseEntity.status(HttpStatus.BAD_REQUEST);
      }
    
    Run Code Online (Sandbox Code Playgroud)

但是,我缺少 DataAccessException。那么,我实际上必须执行以下操作吗:

    @DeleteMapping("/{id}")
    public ResponseEntity<Long> deleteEmployee(@PathVariable Long id) {
        try {
            Long deletedEmployeeId = employeeService.deleteEmployee(id);
            if (deletedEmployeeId != null) {
                return ResponseEntity.ok(deletedEmployeeId);
            } else {
                return ResponseEntity.status(HttpStatus.BAD_REQUEST);
            }
         } catch (DataAccessException e) {
             return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
         }
Run Code Online (Sandbox Code Playgroud)

老实说,这看起来有点过度杀戮。

  • 我仍然有点不确定如何处理保存调用。在我发布这个问题之前,我的控制器只是做了以下操作:

      @PostMapping
      public ResponseEntity<Employee> saveEmployee(@RequestBody Employee employee) {
          return ResponseEntity.ok(employeeService.saveEmployee(employee));
      }
    
    Run Code Online (Sandbox Code Playgroud)

employeeService.saveEmployee(employee)如果抛出 DataAccessException会发生什么?当我将响应包装在 中时,我是否仍然返回 HTTP 状态代码 200 ResponseEntity.ok()

如果是这样,我建议执行以下操作:

    @PostMapping
    public ResponseEntity<Employee> saveEmployee(@RequestBody Employee employee) {
        try {
            Employee savedEmployee = employeeService.saveEmployee(employee);
            return ResponseEntity.ok(savedEmployee);
        } catch (DataAccessException e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
Run Code Online (Sandbox Code Playgroud)

这是人做的事吗?或者 DataAccessExceptions 通常会被忽略,因为它们不是预期的?

小智 1

“save”方法总是返回您要保存的相同对象。仅通过检查“id”,您就可以查看该对象是否已保存。但是,如果数据库中发生错误,则会引发异常,您可以通过将“employeeRepository.save(employee)”放入 try-catch 块中来捕获该异常。与删除deleteById 的方法相同