【问题标题】:How to make "order by aggregate function" in Spring Data?如何在 Spring Data 中进行“按聚合函数排序”?
【发布时间】:2012-11-20 02:19:20
【问题描述】:

我有两个实体:

资源文件:

@Entity
@Table(name = "resource_file")
public class ResourceFile extends IdEntity<Integer> {

    @Id
    @SequenceGenerator(name = "resource_file_id_generator", sequenceName = "resource_file_id", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "resource_file_id_generator")
    @Column(name = "id", unique = true, nullable = false)
    @Nonnegative
    private Integer id;

    ...
}

收藏资源文件:

@Entity
@Table(name = "favorite_resource_file")
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class FavoriteResourceFile extends IdEntity<FavoriteResourceFileId> {

    @EmbeddedId
    private FavoriteResourceFileId id;

    @MapsId("resourceFileId")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "resource_file_id", nullable = false)
    private ResourceFile resourceFile;

    ...

}

我想进行以下查询“选择所有资源文件并按最喜欢的资源文件的数量对其进行排序”。

在 SQL 中它看起来像:

select rf.id, count(frf.resource_file_id) from resource_file rf
left join favorite_resource_file frf on frf.resource_file_id = rf.id
group by rf.id
order by count(rf.id) desc;

但我不明白如何使用 Spring Data 进行操作,以及最后如何映射到 ResourceFile 实体。

一些限制:

  • 我无法在 ResourceFile 中与 FavoriteResourceFile 建立关系, 因为它们位于不同的模块中
  • 我不想使用原生 SQL 或 JPA 查询(作为字符串)。
  • 最好使用元模型、规范或 QueryDSL,因为它们已在项目中使用。

有人可以帮我吗?

【问题讨论】:

    标签: java spring jpa spring-data spring-data-jpa


    【解决方案1】:

    您可以将自定义存储库实现与 Crud/PagingAndSorting 存储库实现一起使用,如下所示:

    端点回购:

    public interface ResourceFileRepository extends
        PagingAndSortingRepository<ResourceFile, Integer>,
        ResourceFileRepositoryCustom {
    }
    

    自定义仓库:

    public interface ResourceFileRepositoryCustom {
        List<ResourceFile> getResourceFilesOrderByFavourites();
    }
    

    使用实际代码的自定义 repo 实现以检索按收藏计数排序的 ResourceFile(注意它是 ResourceFileRepositoryImpl 而不是 ResourceFileRepositoryCustomImpl)。

    我没有那些嵌入式键,所以我不得不稍微简化一下。 查询来自 FavoriteResourceFile,因为 ResourceFile 与 FavoriteResourceFile 没有自己的关系。

    public class ResourceFileRepositoryImpl implements ResourceFileRepositoryCustom {
        @PersistenceContext
        private EntityManager em;
    
        public void setEntityManager(EntityManager em) {
            this.em = em;
        }
    
        @Override
        public List<ResourceFile> getResourceFilesOrderByFavourites() {
            CriteriaBuilder criteriaBuilder = this.em.getCriteriaBuilder();
            CriteriaQuery<ResourceFile> q = criteriaBuilder
                    .createQuery(ResourceFile.class);
            Root<FavoriteResourceFile> root = q.from(FavoriteResourceFile.class);
            Join<FavoriteResourceFile, ResourceFile> join = root.join(
                     FavoriteResourceFile_.resourceFile, JoinType.LEFT);
            q.select(join);
            q.groupBy(join.get(ResourceFile_.id));
            q.orderBy(criteriaBuilder.desc(
                          criteriaBuilder.count(
                              join.get(ResourceFile_.id))));
    
            TypedQuery<ResourceFile> query = this.em.createQuery(q);
            return query.getResultList();
        }
    }
    

    查看完整的示例项目(带有一些非常基本的 sql 和测试)- checkout/fork/etc: https://github.com/rchukh/StackOverflowTests/tree/master/13669324

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-13
      • 2020-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-18
      • 2019-04-29
      • 1970-01-01
      相关资源
      最近更新 更多