我有两个实体,Ablum和Image,它们有多对多关系。 我想制作一个标准查询,以获取所有相册和他们有多少图像的计数。 我不想先获取所有专辑然后循环结果以获得计数,因为会有如此多的sql请求。 我已经工作了2晚并且完全迷路了。如果找不到出路,也许我需要回退使用SQL。
答案 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很简单,将它转换为条件查询应该是微不足道的。