我使用来自以下方面的提示和灵感解决了这个难题:
-
使用 Koitoer 的@Query注释限制结果集
-
如何在 JPA 中按 count() 排序 MicSim
- 我自己做详尽的实验
关于 spring 数据,我一直没有意识到的第一件也是最重要的事情是,即使使用自定义方法,人们仍然可以通过简单地将对象作为参数传递来创建分页查询。这是弹簧数据文档可以明确说明的,因为它绝对不明显,尽管功能非常强大。@Query
Pageable
太好了,现在是第二个问题 - 我如何在JPA中按关联集合的大小对结果进行排序?我已经设法来到了以下JPQL:
select new package.AwithBCount(count(b.id) as bCount,c) from A a join a.bes b group by a
其中 AwithBCount 是查询结果实际映射到的类:
public class AwithBCount{
private Long bCount;
private A a;
public AwithBCount(Long bCount, A a){
this.bCount = bCount;
this.a = a;
}
//getters
}
很高兴我现在可以简单地定义我的存储库,如下所示
public interface ARepository extends JpaRepository<A, Long> {
@Query(
value = "select new package.AwithBCount(count(b.id) as bCount,c) from A a join a.bes b group by a",
countQuery = "select count(a) from A a"
)
Page<AwithBCount> findAllWithBCount(Pageable pageable);
}
我赶紧尝试我的解决方案。完美 - 页面被返回,但当我试图按bCount排序时,我感到失望。事实证明,由于这是一个ARepository(不是AwithBCount存储库),spring-data将尝试在A中查找bCount属性,而不是AwithBCount。所以最后我得到了三种自定义方法:
public interface ARepository extends JpaRepository<A, Long> {
@Query(
value = "select new package.AwithBCount(count(b.id) as bCount,c) from A a join a.bes b group by a",
countQuery = "select count(a) from A a"
)
Page<AwithBCount> findAllWithBCount(Pageable pageable);
@Query(
value = "select new package.AwithBCount(count(b.id) as bCount,c) from A a join a.bes b group by a order by bCount asc",
countQuery = "select count(a) from A a"
)
Page<AwithBCount> findAllWithBCountOrderByCountAsc(Pageable pageable);
@Query(
value = "select new package.AwithBCount(count(b.id) as bCount,c) from A a join a.bes b group by a order by bCount desc",
countQuery = "select count(a) from A a"
)
Page<AwithBCount> findAllWithBCountOrderByCountDesc(Pageable pageable);
}
...以及服务级别的一些附加条件逻辑(可能用抽象存储库实现封装)。因此,尽管不是非常优雅,但这使技巧 - 这种方式(具有更复杂的实体)我可以按其他属性进行排序,进行过滤和分页。