Я переписываю NamedQuery в CriteriaQuery в hibernate-jpa-2.1. Исходный NamedQuery содержит порядок, который ссылается на подзапрос с псевдонимом.ORDER BY с использованием подзапроса в Hibernate JPA 2
select new ItemDto ( item.id, item.number, (select count(*) from ClickEntity as click where click.item.id = item.id) as clickCount ) from ItemEntity as item order by clickCount desc
Я не мог найти способ, чтобы использовать псевдоним, чтобы обратиться к полю ClickCount, поэтому я решил, что я мог бы также использовать подзапрос в обоих местах:
public List<ItemDto> getItems() {
...
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<ItemDto> query = criteriaBuilder.createQuery(ItemDto.class);
Root<ItemEntity> item = query.from(ItemEntity.class);
query
.select(
cb.construct(ItemDto.class,
item.get("id"),
item.get("number"),
getClickCount(cb, query, item).getSelection()
)
)
.orderBy(cb.desc(getClickCount(cb, query, item).getSelection()))
TypedQuery<ItemDto> typedQuery = entityManager.createQuery(query);
return typedQuery.getResultList();
}
private Subquery<Long> getClickCount(CriteriaBuilder cb, CriteriaQuery<ItemDto> query, Root<ItemEntity> item) {
Subquery<Long> subquery = query.subquery(Long.class);
Root<ClickEntity> click = subquery.from(ClickEntity.class)
return subquery
.select(cb.count(click.get("id")))
.where(cb.equal(click.get("item").get("id"), item.get("id")));
}
Однако, когда вызова GetItems(), Hibernate бросает следующее исключение при создании TypedQuery:
org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected AST node: query [...]
Проанализированный запрос выглядит так:
select new ItemDto(
generatedAlias0.id,
generatedAlias0.number,
(select count(generatedAlias1.id) from ClickEntity as generatedAlias1 where(generatedAlias1.item.id=generatedAlias0.id))
)
from ItemEntity as generatedAlias0
order by
(select count(generatedAlias2.id) from ClickEntity as generatedAlias2 where(generatedAlias2.item.id=generatedAlias0.id)) desc
Несмотря на ошибку, этот запрос выглядит хорошо для меня. Я протестировал его без предложения order by, а затем он работает так, как ожидалось, поэтому ошибка определенно вызвана этим предложением. Однако, поскольку Подзапрос, очевидно, работает, мне трудно понять, в чем проблема.
То, что я пытался/считать:
- Использование @PostConstruct установить @Transient поле ItemEntity; это не вариант, поскольку в фактическом приложении значение clickCount зависит от параметра Date.
- Заказ после получения результатов; это не вариант, так как заказ должен произойти до применения (необязательного) предельного параметра
- Не использовать getSelection(). Это имеет тот же эффект (даже тот же запрос).
Итак, неудивительно, что этот подход фактически поддерживается Hibernate или мне не хватает (возможно, более простой) альтернативы использовать результат подзапроса в качестве параметра порядка?