2010-08-30 4 views
1

У меня возникла проблема с запросами JPA-2.0 с отношениями. Как можно было бы выбрать любой Dataset с по крайней мере одним Event с type = B?JPA-2.0 Simple Select-Where question

@Entity 
class Dataset { 
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "dataset") 
    public List<Event> events; 
} 

@Entity 
class Event { 
    @ManyToOne 
    @JoinColumn 
    public Dataset dataset; 

    public Type type; 
} 

enum Type { 
    A, B, C 
} 

Моя отправная точка

CriteriaBuilder _builder = em.getCriteriaBuilder(); 
CriteriaQuery<Dataset> _criteria = _builder.createQuery(Dataset.class); 

// select from 
Root<Dataset> _root = _criteria.from(Dataset.class); 
_criteria.select(_root); 

// apply some filter as where-clause (visitor) 
getFilter().apply(
    _root, _criteria, _builder, em.getMetamodel() 
); 

// how to add a clause as defined before? 
... 

Любые идеи по этому поводу. Я попытался создать подзапросы, а также присоединиться, но я как-то сделал это неправильно и всегда получал все наборы данных в качестве результата.

ответ

4

Попробуйте

SELECT d FROM DataSet d WHERE EXISTS 
    (SELECT e FROM Event e WHERE e.dataSet = d and e.type = :type) 

EDIT: Как Паскаль отметил, что выглядит, как вы используете Criteria API. Не так хорошо знакомы с этим, но у меня будет удар.

CriteriaBuilder builder = em.getCriteriaBuilder(); 
CriteriaQuery<Dataset> criteria = builder.createQuery(Dataset.class); 

Root<Dataset> root = criteria.from(Dataset.class); 
criteria.select(root); 

// build the subquery 
SubQuery<Event> subQuery = criteria.subQuery(Event.class); 
Root<Event> eventRoot = subQuery.from(Event.class); 
subQuery.select(eventRoot); 

ParameterExpression<String> typeParameter = builder.parameter(String.class); 
Predicate typePredicate = builder.equal(eventRoot.get(Event_.type), typeParameter)); 

// i have not tried this before but I assume this will correlate the subquery with the parent root entity 
Predicate correlatePredicate = builder.equal(eventRoot.get(Event_.dataSet), root); 
subQuery.where(builder.and(typePredicate, correlatePredicate); 

criteria.where(builder.exists(subQuery))); 

List<DataSet> dataSets = em.createQuery(criteria).getResultList(); 

Фу, который был тяжелой работой. Сейчас я возвращаюсь в Линк.

+0

Похоже, что OP пытается использовать API критериев здесь. –

+0

Спасибо, это сработало для меня. Я также понял, почему мой подход не удался. Я попытался повторно использовать уже выполненный запрос и добавил другое предложение. Hibernate не жаловался на это, но генерировал неправильные псевдонимы (основной запрос и подзапрос имели один и тот же псевдоним, который, очевидно, терпит неудачу). – Jan

+0

Вам нужно добавить 'subquery.select (eventRoot);', а также проверить ваши скобки в предикате 'correlatePredicate'. Наконец, 'builder.not (builder.exists (subQuery))' должен был быть без _not_. Большое вам спасибо за помощь. – Jan