问题
I've written this request mapping to access a ticket by it's id with the optional request parameters ticketType & ticketStatus :
@GetMapping(path = "/tickets/{ticketId}")
@ResponseStatus(value = HttpStatus.OK)
public ResponseEntity<List<TicketResponse>> getTicketsById(@PathVariable("ticketId") final Long ticketId, @RequestParam("ticketType") final String ticketType, @RequestParam("ticketStatus") final String ticketStatus)
Currently the repository contains methods for returning based on either the ticketId or the ticketState :
@Repository
public interface TicketRepository extends JpaRepository<TicketEntity, Long> {
Stream<TicketEntity> findByTicketIdAndTicketState(@Param("ticketId") Long ticketId);
Stream<TicketEntity> findByTicketIdAndTicketState(@Param("ticketId") Long ticketId, @Param("ticketState") String ticketState);
}
How should these endpoints be exposed at the controller layer ?
Currently the endpoint is:
@GetMapping(path = "/{ticketId}")
@ResponseStatus(value = HttpStatus.OK)
public ResponseEntity<List<TicketResponse>> getTicketsByTicketId(
@PathVariable("productId") final Long ticketId, @RequestParam(name = "ticketState", required=false) final String ticketState) {
final List<TicketResponse> ticketsByTicketId = ticketService.getTicketsByTicketId(ticketId);
if(ticketsByTicketId.size() == 0){
return ResponseEntity.ok("No tickets found");
}
else {
return ResponseEntity.ok(ticketsByTicketId);
}
}
Should I add a new endpoint? :
Or update the controller to select which JPA repository method to implement depending on the query ?:
@GetMapping(path = "/{ticketId}")
@ResponseStatus(value = HttpStatus.OK)
public ResponseEntity<List<TicketResponse>> getTicketsByTicketId(
@PathVariable("productId") final Long ticketId, @RequestParam(name = "ticketState", required=false) final String ticketState) {
List<TicketResponse> tickets = null;
if(ticketState == null) {
tickets = ticketService.getTicketsByTicketId(ticketId);
}
else{
tickets = ticketService.getTicketsByTicketIdAndTicketState(ticketId, ticketState);
}
if(ticketsByTicketId.size() == 0){
return ResponseEntity.ok("No tickets found");
}
else {
return ResponseEntity.ok(ticketsByTicketId);
}
}
The JPA repository will be extended further to filter based on many more parameters such as ticketType, ticketDescription . I just mention this as my controller logic will get very complicated if is required to check which parameter is null and the select the relevant JPA query.
回答1:
Using Spring Data JPA Specification this map filtering problem can be solved. Complex queries can be build using the Criteria API depends on the filtering parameter.
A good article about JPA Specification
来源:https://stackoverflow.com/questions/61041979/mapping-controller-endpoints-to-spring-jpa-layer