当前位置: 首页 > 知识库问答 >
问题:

使用Spring数据JpaRepository按计数排序

南门英飙
2023-03-14

我使用的是Spring数据JpaRepository,我发现它非常容易使用。我实际上需要所有这些功能——分页、排序、过滤。不幸的是,有一件令人讨厌的事情似乎迫使我退回到普通JPA的使用上来。

我需要按关联集合的大小订购。例如,我有:

@Entity
public class A{
    @Id
    private long id;
    @OneToMany
    private List<B> bes;
//boilerplate
}

我必须按bes排序。size()

是否有办法以某种方式自定义排序,仍然利用分页、过滤和其他Spring Data的强大功能?

共有3个答案

赫连智
2023-03-14

谢谢你,艾伦·海伊,这个解决方案对我很有效。我只需设置SecondaryTable注释的foreignKey属性,一切都正常(否则Spring Boot会尝试向id添加foreignKey约束,这会导致sql视图出错)。

结果:

@SecondaryTable(name = "product_view",
            pkJoinColumns = {@PrimaryKeyJoinColumn(name = "id", referencedColumnName = "id")},
            foreignKey = @javax.persistence.ForeignKey(ConstraintMode.NO_CONSTRAINT))
司寇善
2023-03-14

一种比原始解决方案简单得多并且还有其他好处的选择是创建聚合数据的数据库视图,并通过@秒表@OneToOne将您的实体链接到此。

例如:

create view a_summary_view as
select
   a_id as id, 
   count(*) as b_count, 
   sum(value) as b_total, 
   max(some_date) as last_b_date 
from b 

使用@秒表

@Entity
@Table
@SecondaryTable(name = "a_summary_view", 
       pkJoinColumns = {@PrimaryKeyJoinColumn(name = "id", referencedColumnName= "id")})
public class A{

   @Column(table = "a_summary_view")
   private Integer bCount;

   @Column(table = "a_summary_view")
   private BigDecimal bTotal;

   @Column(table = "a_summary_view")
   private Date lastBDate;
}

现在,您可以仅参考实体A进行排序、归档、查询等。

作为一个额外的优势,您的域模型数据在内存中计算可能很昂贵,例如客户所有订单的总价值,而无需加载所有订单或恢复到单独的查询。

连文栋
2023-03-14

我通过以下提示和灵感解决了这个难题:

  1. Koitoer使用@Query anotations限制结果集

关于spring数据,我没有意识到的第一件也是最重要的一件事是,即使使用自定义方法,也可以通过简单地将Pageable对象作为参数传递来创建分页查询。这是spring数据文档中可以明确说明的,因为它虽然功能非常强大,但并不明显。

太好了,现在是第二个问题——在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排序时,我失望了。事实证明,由于这是一个存储库(而不是AwithBCount存储库),spring数据将尝试在中查找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);
}

...以及服务级别上的一些附加条件逻辑(可能用抽象存储库实现封装)。因此,虽然不是非常优雅,但这让我有了窍门——通过这种方式(拥有更复杂的实体),我可以按其他属性排序,进行过滤和分页。

 类似资料:
  • 问题内容: 我正在使用Spring Data JpaRepository,发现它非常易于使用。我实际上需要所有这些功能- 分页,排序,过滤。不幸的是,有一件令人讨厌的事情似乎迫使我退回到使用普通的JPA。 我需要按相关集合的大小排序。例如,我有: 我必须排序 有没有办法通过分页,过滤和其他Spring Data强大功能来自定义排序? 问题答案: 关于spring-data,我尚未意识到的第一件事也

  • 我有以下实体: 用户: 新闻来源: UsersRepository和NewsSourcesRepository是来自Spring数据JPA的简单JPA存储。其配置如下: 我的测试在第15行抛出一个LazyInitializationException异常。信息是: 未能延迟初始化角色:新闻的集合。实体。用户。使用者新闻源,无法初始化代理-无会话 如果我将我的测试注释为@Transactional

  • 我遇到了一个问题,我需要将两列实体相乘来排序,为了想象,实体是: 我不能使用命名查询,因为我的查询基于用户输入进行了大量筛选(不能将where子句放入查询,因为如果用户没有选择任何值,where子句不能只在查询中)。 为了简单点。我需要类似findAll(谓词,Pageable)的东西,但我需要强制查询按“amount*unitPrice”对其进行排序,但也要保持我的Preditate(过滤器)和

  • 我有这个实体(为简洁起见省略注释): 我必须得到一个不同的值的列表为一个特定的 在我的JpaRepository中我有以下内容: 如果没有注释,则返回ID,而不是值。生成的SQL如下所示: 但我需要的是不同的类别,而不是产品实体。除此之外,我在上面添加了注释。但现在我得到了这个错误: 但是我不能将添加到结果列表中,因为这会使无效,因为是主键。 所以我要么需要一个合适的方法名来自动生成查询,要么需要

  • 我有一张这样的桌子: 我想按组排序,然后按count(名称)排序,然后按rand()排序,结果如下: 我写了这个查询,但是如果我在group和rand之间添加count(Name),它会给我一个坏结果

  • 我有一个使用Spring Boot 1.5.1和Spring Data Rest的数据库服务。我将我的实体存储在MySQL数据库中,并使用Spring的PagingAndSorting Repository通过REST访问它们。我发现这表明支持按嵌套参数排序,但我找不到按嵌套字段排序的方法。 我有以下课程: 例如,当使用该方法时: 并调用 URI http://localhost:8080/peo