I have two entities, Ablum and Image, which are in many to many relationship. I wanna make a criteria query that to get all Albums and the counts on how many Images they have. I don't want to get all Albums first then loop the result to get the counts as there would be so many sql requests. I've been working for 2 nights and complete lost. If cannot find a way out maybe I need to fallback to use SQL.
2 Answers
Thanks to digitaljoel's inspiration, I found that CriteriaBuilder has a method call "size" that can be put on collections. Below is the code:
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));
Here the groupBy call is a must otherwise error will occur. But this method is to load the IDs of AlbumEntity, not the entity itself. The Album entity can be load if below code is used:
query.select(cb.array(albums, cb.size(albums.get(AlbumEntity_.images))));
query.groupBy(albums.get(AlbumEntity_.id), ...);
The groupBy must include all properites of the album entity. And it still does not work if the album entity has blob type property.

- 51
- 6
I'm going to have to make some assumptions since you haven't posted your JPA mapping, so I'm assuming each album has a List<YourImageClass> images
for the many to many mapping. With that, something like this would work.
select a, size(a.images) from Album a
That would return a List<Object[]>
where List.get(i)[0]
would be the album and List.get(i)[1]
would be the corresponding size of the image collection.
Alternately, you could define a simple bean to select into. Something like
public class AlbumResult {
private Album album;
private Integer imageCount;
public AlbumResult( Album a, Integer size ) {
album = a;
imageCount = size;
}
// getters and setters here
}
Then you could do
select new AlbumResult(a, size(a.images)) from Album a;
I never deal with criteria queries, but the JPQL is simple enough it should be trivial to translate it into a criteria query.

- 26,265
- 15
- 89
- 115
-
Thanks digitaljoel, but i can not use JPQL in the project. But your idea inspired me. Thanks a lot:) – hzywind Aug 26 '11 at 13:33
-
Yeah, you mentioned that you needed a criteria query in your question, that's why in my answer I said that the JPQL should be simple enough to translate into a criteria query, but since I don't ever use criteria queries I figured you would get that done much quicker than I would. Here's where I got the size function from http://www.objectdb.com/java/jpa/query/jpql/collection#Criteria_Query_Collection_Expressions_ – digitaljoel Aug 26 '11 at 15:08