在 Pageable 中传递给 Spring 控制器的排序将方向附加到 属性 名称,导致 SQL 错误
Sort passed in Pageable to Spring controller appends direction to property name, causing a SQL error
我需要从另一个 Spring 启动应用程序调用我的 Spring 启动应用程序中的可分页端点。我试图将可分页选项从第一个应用程序传递到第二个应用程序,但我遇到了 属性 名称作为 firstName: ASC
出现的问题。当方向附加到它时,它变成 firstName: ASC: ASC
导致 JPA 查询抛出异常。
将可分页选项从我的第一个端点传递到我的第二个端点的正确方法是什么?
调用应用程序
@GetMapping("/v1/users")
public Flux<User> getUsersByAccount(@RequestParam Long accountId,
@PageableDefault(size = 10, sort = "firstName") Pageable pageable) {
return userService.getUsersByAccount(accountId, pageable);
}
public Flux<User> getUsersByAccount(Long accountId, Pageable pageable) {
int page = pageable.getPageNumber();
int size = pageable.getPageSize();
Sort sort = pageable.getSort();
return webClient.backendService()
.get().uri(builder -> builder
.path("/rest/users")
.queryParam("accountId", accountId)
.queryParam("page", page)
.queryParam("size", size)
.queryParam("sort", sort)
.build())
.retrieve()
.bodyToFlux(ContactInfo.class);
}
我将 Pageable 拆分成它的组件,因为我不确定如何一次传递整个对象,因为它不是第二个应用程序中的命名参数。请注意,在这一点上,排序看起来很好,并且显示为 firstName
和 ASC
分别作为 属性 名称和方向的单独值。
调用的应用程序
@GetMapping("/rest/users")
public List<User> getUsersByAccount(@RequestParam Long accountId, Pageable pageable) {
return userService.getUsersByAccount(accountId, pageable);
}
作为@M。 Deinum 提到,Sort
的 toString()
不会产生可以直接序列化回 Sort
对象的表示,(并且对象上没有这样的方法可以做到这一点) .
您可以像这样将其转换为正确的形式:
List<String> sorts = new ArrayList<>();
sort.forEach(order -> sorts.add(String.join(",", order.getProperty(), order.getDirection().toString())));
builder.queryParam("sort", sorts.toArray());
这会生成 ["propertyName,direction"]
的正确表示。
controller我们可以如下抓取HttpServletRequest
public ResponseEntity<Page<PriceBook>> getAll(HttpServletRequest servletRequest) {
return new ResponseEntity<>(priceBookService.findAll(servletRequest), HttpStatus.OK);
}
如下使用queryString将所有请求参数传递给后端服务
public PageableResponse<PriceBook> getPbAllWithFilter(HttpServletRequest servletRequest) {
return webClient.get().uri(pbUrl.concat("?").concat(servletRequest.getQueryString()))
.accept(MediaType.APPLICATION_JSON)
.header(CORRELATION_ID, MDC.get(CORRELATION_ID_MDC))
.exchange()
.flatMap(this::getSubscriptionAll)
.block();
}
我需要从另一个 Spring 启动应用程序调用我的 Spring 启动应用程序中的可分页端点。我试图将可分页选项从第一个应用程序传递到第二个应用程序,但我遇到了 属性 名称作为 firstName: ASC
出现的问题。当方向附加到它时,它变成 firstName: ASC: ASC
导致 JPA 查询抛出异常。
将可分页选项从我的第一个端点传递到我的第二个端点的正确方法是什么?
调用应用程序
@GetMapping("/v1/users")
public Flux<User> getUsersByAccount(@RequestParam Long accountId,
@PageableDefault(size = 10, sort = "firstName") Pageable pageable) {
return userService.getUsersByAccount(accountId, pageable);
}
public Flux<User> getUsersByAccount(Long accountId, Pageable pageable) {
int page = pageable.getPageNumber();
int size = pageable.getPageSize();
Sort sort = pageable.getSort();
return webClient.backendService()
.get().uri(builder -> builder
.path("/rest/users")
.queryParam("accountId", accountId)
.queryParam("page", page)
.queryParam("size", size)
.queryParam("sort", sort)
.build())
.retrieve()
.bodyToFlux(ContactInfo.class);
}
我将 Pageable 拆分成它的组件,因为我不确定如何一次传递整个对象,因为它不是第二个应用程序中的命名参数。请注意,在这一点上,排序看起来很好,并且显示为 firstName
和 ASC
分别作为 属性 名称和方向的单独值。
调用的应用程序
@GetMapping("/rest/users")
public List<User> getUsersByAccount(@RequestParam Long accountId, Pageable pageable) {
return userService.getUsersByAccount(accountId, pageable);
}
作为@M。 Deinum 提到,Sort
的 toString()
不会产生可以直接序列化回 Sort
对象的表示,(并且对象上没有这样的方法可以做到这一点) .
您可以像这样将其转换为正确的形式:
List<String> sorts = new ArrayList<>();
sort.forEach(order -> sorts.add(String.join(",", order.getProperty(), order.getDirection().toString())));
builder.queryParam("sort", sorts.toArray());
这会生成 ["propertyName,direction"]
的正确表示。
controller我们可以如下抓取HttpServletRequest
public ResponseEntity<Page<PriceBook>> getAll(HttpServletRequest servletRequest) {
return new ResponseEntity<>(priceBookService.findAll(servletRequest), HttpStatus.OK);
}
如下使用queryString将所有请求参数传递给后端服务
public PageableResponse<PriceBook> getPbAllWithFilter(HttpServletRequest servletRequest) {
return webClient.get().uri(pbUrl.concat("?").concat(servletRequest.getQueryString()))
.accept(MediaType.APPLICATION_JSON)
.header(CORRELATION_ID, MDC.get(CORRELATION_ID_MDC))
.exchange()
.flatMap(this::getSubscriptionAll)
.block();
}