Сортировка jpa данных Spring по размеру коллекции вложенных объектов

Я использую приложение для весенней загрузки, и существуют следующие 2 объекта.

Person.java

@Entity
@Data
@EqualsAndHashCode(callSuper = true)
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "PERSON")
public class Person extends BaseEntity {
    @NotNull
    @Enumerated(EnumType.STRING)
    private StatusType status;

    @JsonIgnore
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(
            name = "PERSON_ADDRESS",
            joinColumns = @JoinColumn(
                    name = "person_id", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(
                    name = "address_id", referencedColumnName = "id"))
    private Collection<Info> addresses;
}

Address.java

@Entity
@Data
@EqualsAndHashCode(callSuper = true)
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "ADDRESS")
public class Address extends BaseEntity {
    @NotNull
    private String address;

    @ManyToMany(mappedBy = "addresses")
    private Collection<Person> persons;
}

Я использую JpaRepository следующим образом.

@Repository
public interface PersonRepository extends JpaRepository<Person, Long> {
}

И я использую следующий оператор для разбивки на страницы и сортировки.

Page<Person> allPersons = personRepository.findAll(pageable);

где pageable - это экземпляр org.springframework.data.domain.Pageable.

Я могу сортировать, используя другие столбцы в Person. Но я хочу отсортировать на основе набора адресов, основываясь на количестве записей Address для каждого объекта Person.

Короче хотел отсортировать Лица на основе размера коллекции Collection. Порядок сортировки (ASC или DESC) поступает от внешнего интерфейса.

Есть идеи, как должен выглядеть объект Pageable для реализации этого? Также без возврата дубликатов записи Person, если для Address существует более одного Person.

Spring Data JPa имеет много очень эффективных функций, но не всемогущ. Вам необходимо создать уникальный запрос ... или спецификацию, потому что вы можете использовать его вместе с Pageable.

Selindek 13.09.2018 11:13
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
1
4 725
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вот решение по Порядок по количеству с использованием Spring Data JpaRepository.

В своем эксперименте я попытался определить репозиторий следующим образом, но с этим возникла проблема; поскольку мы определяем запрос на PersonRepository для сортировки на основе данных spring addressCount, просматривает Person.

@Repository
public interface PersonRepository extends JpaRepository<Person, Long> {

    @Query(
        value = "select p from Person p join p.addresses ad group by p",
        countQuery = "select count(p) from Person p"
    )
    Page <Person> findAllWithAddressCount(Pageable pageable);
}

В качестве обходного пути я попытался перенести логику сортировки в само определение запроса, и в итоге я получил 2 версии для режимов ASC и DESC:

@Repository
public interface PersonRepository extends JpaRepository <Person, Long> {

    @Query(
        value = "select p from Person p join p.addresses ad group by p Order By addressCount asc",
        countQuery = "select count(p) from Person p"
    )
    Page<Person> findAllOrderByAddressCountAsc(Pageable pageable);

    @Query(
        value = "select p from Person p join p.addresses ad group by p Order By addressCount desc",
        countQuery = "select count(p) from Person p"
    )
    Page<Person> findAllOrderByAddressCountDesc(Pageable pageable);
}

Надеюсь, это поможет.

А как будет выглядеть поле сортировки объекта Pageable?

Philip John 13.09.2018 11:47

Кроме того, если есть только 6 человек, у 3 из которых есть 2 адреса, а у остальных - по одному адресу, тогда, если мы воспользуемся этим countQuery, я получу записи 9 человек, верно? С 3 из них дублируются

Philip John 13.09.2018 11:48

@PhilipJohni, я поэкспериментировал и изменил предложенное мной решение, пожалуйста, проверьте

MohammadReza Alagheband 13.09.2018 12:38

Хм, я видел это решение в другом сообщении stackoverflow и хотел узнать, есть ли какой-либо альтернативный способ. Возможно, вы можете добавить ссылку на исходный ответ в качестве ссылки на свой ответ.

Philip John 14.09.2018 12:58

Ссылка @PhilipJohn дана

MohammadReza Alagheband 15.09.2018 07:22

Другие вопросы по теме