简体   繁体   English

请求 Spring Data JPA 存储库时指定复杂的排序标准

[英]Specify complex sorting criteria when requesting Spring Data JPA repository

I'm requesting paged and sorted data from my database, specified via Pageable with following repository API:我正在从我的数据库中请求分页和排序的数据,这些数据是通过Pageable指定的,带有以下存储库 API:

org.springframework.data.jpa.repository.JpaSpecificationExecutor.findAll(Specification<MyEntity> filter, Pageable pageable)

Pageable contains a Sort with simple sorting criteria, such as sort column X in descending order . Pageable包含一个具有简单排序条件的Sort ,例如对 X 列进行降序排序

Sometimes, Sort contains one column which actually doesn't exist in the underlying table, which must be replaced by a complex conditional ORDER BY expression:有时, Sort包含一个在基础表中实际上不存在的列,必须用复杂的条件ORDER BY表达式替换:

ORDER BY CASE WHEN entity_to='CUSTOMER' THEN entity_to_id ELSE (CASE WHEN entity_from='CUSTOMER' THEN entity_from_id END) END

Indeed, I can rebuild the Sort instance in Pageable so that this non-existing column gets removed, but I didn't find a way to inject the complex ORDER BY expression in that case.实际上,我可以在Pageable中重建Sort实例,以便删除这个不存在的列,但在这种情况下我没有找到注入复杂ORDER BY表达式的方法。

I tried to find a way, to enrich the resulting query from this invocation of the Repository.我试图找到一种方法来丰富来自此存储库调用的结果查询。 I hoped that I can do it by adding another Specification filter, but I got an error ( No explicit selection and an implicit one could not be determined ), and I'm not sure that the order-by will be applied to the final query built by the Repository implementation:我希望我可以通过添加另一个Specification过滤器来做到这一点,但是我得到了一个错误( No explicit selection and an implicit one could not be determined ),而且我不确定 order-by 是否会应用于最终查询由存储库实现构建:

...
filter = filter.and(
        (root, query, cb) -> {
            final var customerLiteral = cb.literal("CUSTOMER");
            final var caseExpression = cb.selectCase(root.get(MyEntity_.ENTITY_TO))
                    .when(customerLiteral, root.get(MyEntity_.ENTITY_TO_ID)).otherwise(
                            cb.selectCase(root.get(MyEntity_.ENTITY_FROM))
                                    .when(customerLiteral, root.get(MyEntity_.ENTITY_FROM_ID)).otherwise(0));
            final var order = ascElseDesc ? cb.asc(caseExpression) : cb.desc(caseExpression);

            final var cq = cb.createQuery(MyEntity.class);
            return cb.exists(cq.select(root).orderBy(order).subquery(MyEntity.class));
        }
);

repository.findAll(filter, pageable);

I don't want to drop the current implementation which leverages Spring Data's findAll(filter, pageable) .我不想放弃利用 Spring Data 的findAll(filter, pageable)的当前实现。 I only would like to enrich it in one case.我只想在一种情况下丰富它。 How can it be done?怎么做到呢?

对于这种情况,您可以使用自定义 SQL 在MyEntity中创建@Formula列,然后在Pageable中将其作为常规实体字段引用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM