复杂的多对多 JPA CriteriaQuery

Posted

技术标签:

【中文标题】复杂的多对多 JPA CriteriaQuery【英文标题】:Complex Many-to-Many JPA CriteriaQuery 【发布时间】:2011-08-25 15:11:25 【问题描述】:

我有两个实体,Ablum 和 Image,它们之间存在多对多关系。 我想做一个标准查询来获取所有专辑以及他们拥有多少张图片的计数。 我不想先获取所有专辑然后循环结果以获取计数,因为会有很多 sql 请求。 我已经工作了两个晚上,完全迷路了。如果找不到出路,也许我需要回退到使用 SQL。

【问题讨论】:

【参考方案1】:

感谢 digitaljoel 的启发,我发现 CriteriaBuilder 有一个方法叫做“size”,可以放在集合上。下面是代码:

    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 类型属性,它仍然不起作用。

【讨论】:

【参考方案2】:

由于您尚未发布 JPA 映射,因此我将不得不做出一些假设,因此我假设每张专辑都有一个用于多对多映射的 List&lt;YourImageClass&gt; images。有了这个,这样的事情就可以了。

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

这将返回一个List&lt;Object[]&gt;,其中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 很简单,将其转换为条件查询应该很简单。

【讨论】:

感谢 digitaljoel,但我不能在项目中使用 JPQL。但是你的想法启发了我。非常感谢:) 是的,您提到您在问题中需要一个条件查询,这就是为什么在我的回答中我说 JPQL 应该足够简单以转换为条件查询,但因为我从来没有使用标准查询我认为你会比我更快地完成这项工作。这是我从objectdb.com/java/jpa/query/jpql/…获得大小函数的地方@

以上是关于复杂的多对多 JPA CriteriaQuery的主要内容,如果未能解决你的问题,请参考以下文章

JPA中的多对多双向映射

使用 JPA 映射与属性的多对多关系

使用 JPA 和 Hibernate 提供程序的多对多关系不会创建主键

清除与 JPA / JPQL 的多对多关系

与 Play Framework 1.2.5 JPA 的多对多关系

JPA 2:通过不在带有额外字段的多对多中工作来订购