【发布时间】:2023-02-10 10:18:06
【问题描述】:
我正在使用 Spring Data JPA 来处理数据库调用。为此,我创建了:
-
一个 EmployeeRepository 接口,它扩展了
JpaRepository<Employee, Long> -
一个 EmployeeService,它定义了三个方法:
Employee saveEmployee(Employee employee); Optional<Employee> getEmployee(Long id); Long deleteEmployee(Long id); -
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; }问题如下:
get-methods 工作正常,可以返回一个可选的。另一方面,保存方法不能返回一个可选的。显然 JpaRepository 在调用 save() 时返回已保存对象的实例。我宁愿返回一个可选的,因为在保存员工时可能会出错,在这种情况下,我想抛出一个错误——即,只要可选不存在,我就会抛出一个错误。
删除操作也是如此:例如,如果我要求删除一个员工并传入一个不存在的 id 怎么办?如果删除操作成功,我想捕获此错误,然后才返回传入的 ID。为此我必须捕获哪个错误?谁可以给我解释一下这个?
=================================================
更新:
-
我通过简单地在调用 deleteById(id) 之前检查给定的 employee-id 是否存在来解决 delete-call 的问题;如果没有,则服务返回 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); }
但是,我缺少 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) }老实说,这看起来有点矫枉过正。
-
我仍然不确定如何处理保存调用。在我发布这个问题之前,我的控制器只是在做以下事情:
@PostMapping public ResponseEntity<Employee> saveEmployee(@RequestBody Employee employee) { return ResponseEntity.ok(employeeService.saveEmployee(employee)); }
如果
employeeService.saveEmployee(employee)抛出 DataAccessException 会发生什么?当我将响应包装在ResponseEntity.ok()中时,我是否仍会返回 HTTP-status-code 200?如果是这样,我建议执行以下操作:
@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); } }这是人做的事吗?还是 DataAccessExceptions 通常被忽略,因为它们不是预期的?
-
【问题讨论】:
-
当谈到 save() Optional 意味着一个对象可能存在并且不关注数据库约束。对于 delete() JPA 返回 void
-
你试过了吗,@Override public Optional<Employee> saveEmployee(Employee employee) { return Optional.ofNullable(employeeRepository.save(employee)); }
-
对于最后一个问题,如果这是人们所做的事情:我不会为此烦恼。当您的实体无法持久化时,将抛出错误。在你的最后一个例子中,你捕获了异常并产生了一个响应状态 500,但是当你的代码没有处理异常时,Spring 无论如何都会自己做。在某些情况下,您确实想要处理异常,对于简单的 REST 控制器,我看不到任何好处。 (除非您出于任何原因想要生成“可读”的错误消息)。
-
@SimonOelerich 感谢您的评论!那么,您是否建议像最初那样使用倒数第二个示例?在这种情况下,即使发生 DataAccessException(由于 ResponseEntity.ok()),我不是每次都返回 200 的 http 状态吗?
-
是的,只需返回
ResponseEntity.ok(emplyeeRepo.findById(id))就足够了。对于所有保存/查找/删除都很好。除了存储库之外,您很可能不需要该服务。您可以直接调用 JpaRepository 方法,因为异常处理由独立于其来源的 spring 完成。只有在除了简单的 bean 验证之外还有其他业务逻辑时,您才需要它。
标签: java spring-boot hibernate spring-data-jpa