复杂的多对多JPA CriteriaQuery

时间:2011-08-25 15:11:26

标签: jpa many-to-many criteriaquery

我有两个实体,Ablum和Image,它们有多对多关系。 我想制作一个标准查询,以获取所有相册和他们有多少图像的计数。 我不想先获取所有专辑然后循环结果以获得计数,因为会有如此多的sql请求。 我已经工作了2晚并且完全迷路了。如果找不到出路,也许我需要回退使用SQL。

2 个答案:

答案 0 :(得分:3)

感谢digitaljoel的灵感,我发现CriteriaBuilder有一个方法调用“大小”可以放在集合上。以下是代码:

    CriteriaBuilder cb = getCriteriaBuilder();
    CriteriaQuery<Object[]> query = cb.createQuery(Object[].class);
    Root<AlbumEntity> albums = query.from(AlbumEntity.class);
    query.select(cb.array(albums.get(AlbumEntity_.id), cb.size(albums.get(AlbumEntity_.images))));
    query.groupBy(albums.get(AlbumEntity_.id));

此处groupBy调用是必须的,否则将发生错误。 但是这种方法是加载AlbumEntity的ID,而不是实体本身。如果使用以下代码,则可以加载相册实体:

    query.select(cb.array(albums, cb.size(albums.get(AlbumEntity_.images))));
    query.groupBy(albums.get(AlbumEntity_.id), ...);

groupBy必须包含相册实体的所有属性。如果专辑实体具有blob类型属性,它仍然不起作用。

答案 1 :(得分:2)

我将不得不做出一些假设,因为你还没有发布你的JPA映射,所以我假设每张专辑都有一个List<YourImageClass> images用于多对多的映射。有了这个,这样的东西就可以了。

select a, size(a.images) from Album a

这将返回List<Object[]>List.get(i)[0]将成为相册,List.get(i)[1]将是图片集的相应尺寸。

或者,您可以定义一个要选择的简单bean。像

这样的东西
public class AlbumResult {
    private Album album;
    private Integer imageCount;
    public AlbumResult( Album a, Integer size ) {
        album = a;
        imageCount = size;
    }
    // getters and setters here
}

然后你可以做

select new AlbumResult(a, size(a.images)) from Album a;

我从不处理标准查询,但是JPQL很简单,将它转换为条件查询应该是微不足道的。