Ответ 1
Я решил головоломку, используя подсказки и вдохновения:
- Ограничение результатов с помощью анонсов @Query от Koitoer
- Как заказать по count() в JPA от 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;
}
//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);
}
Я поспешил попробовать свое решение. Perfect - страница возвращается, но когда я пытался сортировать по bCount, я разочаровался. Оказалось, что поскольку это ARepository (не репозиторий AwithBCount), то spring -data попытается найти свойство 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);
}
... и некоторой дополнительной условной логики на уровне обслуживания (которая, вероятно, может быть инкапсулирована реализацией абстрактного репозитория). Итак, хотя и не очень элегантный, это сделало трюк - таким образом (имея более сложные объекты), я могу сортировать по другим свойствам, выполнять фильтрацию и разбивку на страницы.