【问题标题】:How to sort result by multiplying some values in Spring?如何通过在Spring中乘以一些值来对结果进行排序?
【发布时间】:2019-12-25 15:54:03
【问题描述】:

所以,我有模型书,它具有物理尺寸:高度、宽度和长度。我的存储库方法如下所示:

@Query(value = "SELECT b FROM Book b ORDER BY b.bookHeight * b.bookWidth * b.bookLength")
List<Book> getAllBooksOrderedByVolumePaginated(PageRequest request);

我想创建带有查询参数sortOrder 的端点,我可以在其中放置ascdesc 排序顺序。

在服务层有下一个代码:

private Sort.Direction resolveDirection(String order) {
    Sort.Direction orderType = null;

    if (order.equals("desc"))
        orderType = Sort.Direction.DESC;
    else if (order.equals("asc"))
        orderType = Sort.Direction.ASC;

    return orderType;
}

public List<BookDto> findAllBooksSortedByVolume(int page, int size, String order) {
    Sort.Direction orderType = resolveDirection(order);
    List<Book> books = bookRepository.getAllBooksOrderedByVolumePaginated(
            PageRequest.of(page - 1, size, Sort.by(orderType)));

    return mapToDto(books);
}

我得到了指定排序参数的异常:

java.lang.IllegalArgumentException: At least one property must be given!
    at org.springframework.util.Assert.isTrue(Assert.java:118)
    at org.springframework.data.domain.Sort.by(Sort.java:165)
    at ua.com.epam.service.BookService.findAllBooksSortedByVolume(BookService.java:106)
    at ua.com.epam.controller.BookController.getAllBooksSortedInSomeDimension(BookController.java:156)

我该如何解决这个问题?

【问题讨论】:

  • resolveDirection(order) 是如何实现的?
  • @Sebastian,我编辑问题正文
  • 您的Sort.Direction (orderType) 为空,将您的resolveDirection 更改为默认返回ASC
  • @Shadov,不!它检查控制器,如果排序顺序不是 desc 或 asc,API 将为此抛出一个指定的异常
  • 如果在 order by 子句中指定表达式有问题,那么可能是您可以在 select 子句中添加表达式并按其排序SELECT b, b.bookHeight * b.bookWidth * b.bookLength AS x_volume FROM Book b ORDER BY x_volume

标签: java mysql spring sorting


【解决方案1】:

如果你使用 Hibernate 作为 JPA 提供者,那么你可以使用@Formula 来声明一个“虚拟列”。

@Entity
class Book {
    ...
    @Formula("bookHeight * bookWidth * bookLength")
    private long volume;

    // Just in case you want to access volume in java code.
    // If you don't want then remove `getVolume` from class
    @Transient
    public long getVolume() { 
        return volume;
    }
    ...
}

并按此列排序

PageRequest.of(page - 1, size, Sort.by(orderType, "volume"))

【讨论】:

    【解决方案2】:

    您至少需要指定一个属性作为排序依据。您指定了方向,但排序也需要一个属性。查看Sort.by的实现:

    public static Sort by(Direction direction, String... properties) {
        Assert.notNull(direction, "Direction must not be null!");
        Assert.notNull(properties, "Properties must not be null!");
        Assert.isTrue(properties.length > 0, "At least one property must be given!");
    
        return Sort.by(Arrays.stream(properties)//
                .map(it -> new Order(direction, it))//
                .collect(Collectors.toList()));
    }
    

    【讨论】:

    • 是的,我知道。但是要排序的属性是 b.bookHeight * b.bookWidth * b.bookLength。我该如何指定它??
    • 你需要告诉他你想按哪一列排序。我不认为你可以通过计算值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-14
    • 2012-06-18
    相关资源
    最近更新 更多