2012-12-02 50 views
5

我有两个实体:如何在Spring Data中进行“按聚合函数排序”?

的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:

@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数据,以及如何做到这一点,使映射到实体的resourcefile在最后。

一些限制:

  • 我不能让有关FavoriteResourceFile中的resourcefile, 因为它们位于不同的模块
  • 我不想使用本地SQL或JPA查询(如字符串)。
  • 最好使用元模型,规范或QueryDSL,因为它们已经在项目中使用。

有人可以帮我吗?

回答

6

您可以使用自定义的仓库实现带有CRUD/PagingAndSorting库实施以来,像这样:

终点回购:

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

定制回购:

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

定制用实际代码回购实现来检索ResourceFile按喜好计数排序(注意它是ResourceFileRepositoryImpl而不是R esourceFileRepositoryCustomImpl)。

我没有那些嵌入式按键,所以我不得不简化一下。 查询将从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和测试) - 结帐/叉的/ etc: https://github.com/rchukh/StackOverflowTests/tree/master/13669324