Reputation: 51
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.
Upvotes: 2
Views: 1426
Reputation: 51
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.
Upvotes: 3
Reputation: 26574
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.
Upvotes: 2