简体   繁体   English

如何在Spring Data中进行“按聚合函数排序”?

[英]How to make “order by aggregate function” in Spring Data?

I have two entities: 我有两个实体:

ResourceFile: 的resourcefile:

@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;

    ...
}

FavoriteResourceFile: FavoriteResourceFile:

@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;

    ...

}

And I want to make the following query "select all resource files and sort them by favourite resource file's count". 我想进行以下查询“选择所有资源文件并按喜欢的资源文件的计数对它们进行排序”。

In SQL it looks like: 在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;

But I can't understand how to do it with Spring Data and how to make mapping to ResourceFile entity at the end. 但我无法理解如何使用Spring Data以及如何在最后映射到ResourceFile实体。

Some limitations: 一些限制:

  • I can't make relation to FavoriteResourceFile in ResourceFile, because they are located in different modules 我无法在ResourceFile中与FavoriteResourceFile建立关系,因为它们位于不同的模块中
  • I don't want to use native SQL or JPA query (as strings). 我不想使用本机SQL或JPA查询(作为字符串)。
  • It'll be preferable to use Meta-models, Specification or QueryDSL, because they are already used in project. 最好使用元模型,规范或QueryDSL,因为它们已经在项目中使用。

Can someone help me? 有人能帮我吗?

You can use your custom repository implementation along with Crud/PagingAndSorting repository implementation, like this: 您可以使用自定义存储库实现以及Crud / PagingAndSorting存储库实现,如下所示:

End-point repo: 终点回购:

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

Custom repo: 定制回购:

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

Custom repo implementation with actual code to retrive ResourceFile's ordered by favourite count (notice it is ResourceFileRepositoryImpl and not ResourceFileRepositoryCustomImpl). 使用实际代码自定义repo实现以按最喜欢的计数顺序检索ResourceFile(注意它是ResourceFileRepositoryImpl而不是ResourceFileRepositoryCustomImpl)。

I didn't have those embeded keys, so I had to simplify it a little bit. 我没有那些嵌入式键,所以我不得不简化一下。 The query is going FROM the FavoriteResourceFile, because ResourceFile don't have own relation to FavoriteResourceFile. 查询来自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();
    }
}

To see full example project (with some very basic sql and test) - checkout/fork/etc: https://github.com/rchukh/StackOverflowTests/tree/master/13669324 要查看完整的示例项目(使用一些非常基本的SQL和测试) - checkout / fork / etc: https//github.com/rchukh/StackOverflowTests/tree/master/13669324

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM