2012-12-02 84 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