我使用以下提示和灵感解决了这个谜题:
- 通过使用@Query注释限制结果集 ,作者为Koitoer
- 如何在JPA中按count()排序,作者为MicSim
- 通过自己进行全面的实验。
我之前不知道关于 spring-data 的第一件最重要的事情是,即使使用@Query
自定义方法,也可以通过简单地将Pageable
对象作为参数传递来创建分页查询。这是一项非常强大的功能,尽管它并不明显,但它本应该由spring-data文档明确说明。
好的,现在是第二个问题 - 如何在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;
}
}
我很兴奋,因为现在我可以像下面这样简单地定义我的代码库
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 repository),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);
}
...而且还有一些针对服务级别的附加条件逻辑(可以通过抽象仓库实现封装)。因此,虽然不是非常优雅,但这样做很有用——通过这种方式(拥有更复杂的实体),我可以按其他属性进行排序、筛选和分页。
c
的位置AwithBCount(count(b.id) as bCount,c)
,而且你不需要写count(b.id) as bCount
,只写count(b.id)
就可以了。 - azerafatiA
类型不同的Page
?! 在尝试此解决方案时,我收到了一个错误,指出AwithBCount
是未映射的实体。 - miran