Search code examples
javahibernatefilteringcriteriaone-to-many

Hibernate Criteria API - Filtering collection property


I have such entity:

@Entity
public class Album {

    private Integer id;
    private Integer ownerId;
    private String name;
    private String description;
    private Date created;
    @OneToMany @JoinColumn(name = "albumId")
    private Set<AlbumUser> users = new HashSet<AlbumUser>();
    @OneToMany @JoinColumn(name = "albumId")
    private Set<Picture> pictures = new HashSet<Picture>();
}

and another one:

@Entity
public class Picture {

    private Integer id;
    private Integer creatorId;
    private Integer albumId;
    private Date created;
    private String title;
    private String description; 
    @ManyToOne @JoinColumn(name = "eventId")
    private Event event;
}

Using Criteria API I want to get unique AlbumDs with filtered set of Picturs. I try something like this:

public Album read(Integer albumId, Set<Integer> picFilter) {
        Criteria crit = getCurrentSession().createCriteria(Album.class, "album");
        crit.add(Restrictions.idEq(albumId));
        if (picFilter != null && !picFilter.isEmpty()) {
            crit = crit.createAlias("album.pictures", "picture");
            crit.add(Restrictions.in("picture.event.id", picFilter));
            crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);   
        }       
        Album resultDs = (Album) crit.uniqueResult();       
        return resultDs;
}

And here I get Album with all pictures associated. They're not filtered at all. When I try to execute query printed by a logger, I get only four rows wich is the number of pictures with given eventId, but in the Album I get all pictures.

I also tried other ResultTransformers, but eventualy got many result (4) not distinct one.

What do I miss or do wrong?


Solution

  • You can not filter the content of Collections associated with an entity by including Restrictions on the Collection in the query. The query will only fetch the Albums. The content of the Collection can be fetched later, when the Collection is accessed. All you do is filter the Albums to retrieve only those Albums that contain the Pictures with the event ids.

    If the Collection would only contain the Pictures that match your Criteria and you would get a partial Collection it would cause problems on updates, because Hibernate then think the filtered items have been removed and would update the database to reflect that change, actually removing the items from the Collection.

    If you want to receive only some items from a Collection you can use the Session.createFilter() method. The only problem is, that it only supports HQL queries currently.