2010-10-08 3 views
5
public enum ReportStatus { 
    SUCCCEED, FAILED; 
} 

public class Work { 
    @ElementCollection 
    @Enumerated(EnumType.STRING) 
    List<ReportStatus> reportStatuses; 
} 

Учитывая такую ​​структуру, я хотел бы выполнить запрос, чтобы найти всю работу отфильтрованной reportStatuses. Он отлично работает со следующим HQL синтаксисом:Использование @ElementCollection в CriteriaQuery (или Запрашивание над содержанием в @ElementCollection)

public List<Long> queryHQL() { 
    final String query = "SELECT w.id FROM Work w JOIN w.reportStatuses s WHERE s in (:rs)"; 

    final List<ReportStatus> reportStatuses = new ArrayList<ReportStatus>(); 
    reportStatuses.add(ReportStatus.FAILED); 

    return this.entityManager.createQuery(query).setParameter("rs", reportStatuses).getResultList(); 
} 

Но я хотел бы использовать критерии API (jpa2), и не может понять, как это сделать. Вот мой ближайший попробовать я думаю:

public List<Long> query() { 
    final List<ReportStatus> reportStatuses = new ArrayList<ReportStatus>(); 
    reportStatuses.add(ReportStatus.FAILED); 

    final CriteriaBuilder builder = this.entityManager.getCriteriaBuilder(); 

    final CriteriaQuery<Long> criteriaQuery = builder.createQuery(Long.class); 
    final Root<Work> workModel = criteriaQuery.from(Work.class); 

    final ListJoin<Work, ReportStatus> status = workModel.joinList("reportStatuses"); 

    final Predicate predicate = status.in(reportStatuses); 

    criteriaQuery.where(predicate); 
    criteriaQuery.select(workModel.<Long> get("id")); 

    return this.entityManager.createQuery(criteriaQuery).getResultList(); 
} 

Я также попытался с критериями Hibernate API, но как jpa2 один я не смог найти правильный синтаксис.

+0

ël проверить обновленный ответ. – dira

ответ

4

Я бы использовал следующий синтаксис CriteriaQuery для выполнения той же самой вещи.

EntityManager em = entityManagerFactory.createEntityManager(); 

final List<ReportStatus> reportStatuses = new ArrayList<ReportStatus>(); 
reportStatuses.add(ReportStatus.FAILED); 

final CriteriaBuilder builder = em.getCriteriaBuilder(); 

final CriteriaQuery<Long> criteriaQuery = builder.createQuery(Long.class); 
final Root<Work> _work = criteriaQuery.from(Work.class); 

/*final ListJoin<Work, ReportStatus> status = _work.joinList("reportStatuses"); 
final Predicate predicate = status.in(reportStatuses); 
criteriaQuery.where(predicate);*/ 

final Expression<List<ReportStatus>> _status = _work.get(Work_.reportStatuses); 
_status.in(reportStatuses); 

criteriaQuery.select(_work.get(Work_.id)); 

List<Long> list = em.createQuery(criteriaQuery).getResultList(); 

UPDATE

Спасибо, но мы не используем сгенерированный метамодели. К сожалению, Я не могу попробовать ответить. :(

Если вы не используете метамодель, просто замените _work.get(Work_.reportStatuses) с _work.get("reportStatuses"). Он будет работать. :)

+0

Спасибо, но мы не используем созданную метамодель. К сожалению, я не могу попробовать ответить. :( –

+0

@ Raphaël Brugier Проверьте часть UPDATE. – dira

+0

Спасибо! Кажется, сейчас работает. –

1

Я запутался. Вызов in(..) возвращает предикат, но, похоже, не выполняет его (он, кажется, не интегрирован в запрос —, по крайней мере, для меня он возвратил все члены корня, пересекались ли их коллекции с reportStatuses. журнал отладки показывает простой запрос select distinct work0_.id as id18_ from Work work0_).

Кроме того, зачем беспокоиться о том, чтобы поставить reportStatuses в список, если вызывающий объект интересуется только теми, которые соответствуют одному значению? Как бы вы делали запрос с помощью только ReportStatus.FAILED вместо создания списка для него?

3

Вы можете создать этот HQL.

String query = "SELECT w.id FROM Work w, IN(w.reportStatuses) s WHERE s = :rs"; 
return this.entityManager.createQuery(query).setParameter("rs", ReportStatus.FAILED).getResultList(); 
+0

Я хотел бы указать, что некоторые вспомогательные инструменты JPA SQL отметят это как ошибку, когда вы помещаете '@ ElementCollection' в' in (~) ', НЕ доверяйте этим инструментам (в этом случае), это работает без потерь и довольно быстро, если вы индексируете правильные поля (этот ответ помог мне сэкономить несколько часов работы). –

+0

Где вы нашли эту функцию? во всем Интернете, пытаясь решить эту точную проблему, и этот ответ является единственным упоминанием использования предложения IN в качестве псевдо-таблицы, которую я нашел. Это работало безупречно! – stevevls

Смежные вопросы