Hibernate Criteria API - фильтрация свойства коллекции - PullRequest
4 голосов
/ 23 мая 2011

У меня есть такая сущность:

@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>();
}

и еще один:

@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;
}

Используя Criteria API, я хочу получить уникальные AlbumD с отфильтрованным набором изображений. Я пытаюсь что-то вроде этого:

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;
}

И вот я получаю альбом со всеми связанными картинками. Они не фильтруются вообще. Когда я пытаюсь выполнить запрос, напечатанный регистратором, я получаю только четыре строки с количеством изображений с заданным идентификатором события, но в альбоме я получаю все изображения.

Я также пробовал другие ResultTransformers, но в итоге получил много результатов (4) не отличных.

Что я пропускаю или делаю неправильно?

Ответы [ 4 ]

5 голосов
/ 25 мая 2011

Вы не можете фильтровать содержимое коллекций, связанных с сущностью, включив в запрос ограничения на коллекцию. Запрос будет получать только альбомы. Содержимое Коллекции может быть получено позже, когда Доступ к Коллекции. Все, что вам нужно сделать, это отфильтровать альбомы, чтобы получить только те альбомы, которые содержат изображения с идентификаторами событий.

Если коллекция будет содержать только рисунки, соответствующие вашим критериям, и вы получите частичную коллекцию, это вызовет проблемы при обновлении, потому что Hibernate тогда думает, что отфильтрованные элементы были удалены, и обновит базу данных, чтобы отразить это изменение, фактически удаление предметов из коллекции.

Если вы хотите получать только некоторые элементы из Коллекции, вы можете использовать метод Session.createFilter () . Единственная проблема заключается в том, что в настоящее время он поддерживает только HQL-запросы.

1 голос
/ 24 мая 2011

Я помню, это было проблемой из-за того, что я недавно сделал.Вы пробовали это:

if (picFilter != null && !picFilter.isEmpty()) {
    Criteria subCriteria = crit.createCriteria("album.pictures"); // Or just 'pictures?'
    Disjunction or = Restrictions.disjunction();

    for (Integer id : picFilter)
        or.add(Restrictions.idEq(id));
    subCriteria.add(or);
    crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 
 }
0 голосов
/ 10 января 2018

Если вы используете псевдоним с left_join, он вернет только подобъект, который удовлетворяет связанному условию.В противном случае он возвращает основной объект, который удовлетворяет условиям, но со всем установленным подобъектом.

crit = crit.createAlias("album.pictures", "picture", CriteriaSpecification.LEFT_JOIN);

Этот метод устарел в некоторой версии гибернации, если так, вы также можете использовать приведенное ниже решение:отфильтрованный комплексный набор

0 голосов
/ 25 мая 2011

попробуйте это:

    Criteria crit = getCurrentSession().createCriteria(Album.class, "album");
    crit.add(Restrictions.idEq(albumId));
    if (picFilter != null && !picFilter.isEmpty()) {
        crit.createAlias("album.pictures", "picture");
        crit.createAlias("picture.event", "event");
        crit.add(Restrictions.in("event.id", picFilter));
        crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);   
    }     
...