Spring Data JPA按嵌套对象集合大小排序

5
我正在使用 Spring Boot 应用程序,存在以下 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);

其中,pageableorg.springframework.data.domain.Pageable 的实例。

我能够使用 Person 中的其他列进行排序。但是我想基于地址集合对其进行排序,即根据每个 Person 实体的 Address 记录数量进行排序。

简而言之,我想基于 Collection 的大小对 Persons 进行排序。排序顺序(升序或降序)来自前端。

有没有想法如何实现此功能的 Pageable 对象?同时,如果一个 Person 存在多个 Address,则不返回任何重复的 Person 记录。


1
Spring Data JPa有许多非常有效的功能,但它并不万能。您需要创建一个唯一的查询或规范,因为您可以与Pageable一起使用它。 - Selindek
1个回答

6

以下是根据Order by count using Spring Data JpaRepository的解决方案。

在我的实验中,我尝试按照以下方式定义Repository,但存在问题;因为我们正在定义基于addressCount排序的PersonRepository的查询,Spring Data会查找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);
}

因此,作为一种解决方法,我尝试将排序逻辑移到查询定义中,并最终得到了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);
}

希望这能有所帮助。

分页对象的排序字段会是什么样子? - Philip John
如果只有6个人,其中3个人有2个地址,其余人每人一个地址,那么如果我们使用这个countQuery,我会得到9个人的记录,其中3个是重复的,对吗? - Philip John
@PhilipJohni,我进行了实验并更改了我的建议解决方案,请检查。 - MohammadReza Alagheband
嗯,我在另一篇stackoverflow的帖子中看到了这个解决方案,并想知道是否有其他替代方法。也许您可以将原始答案的链接作为您答案的参考。 - Philip John
@PhilipJohn 给定的参考。 - MohammadReza Alagheband
1
addressCount 是什么? - Jorge Guillermo Negrete

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接