Напишите предложение HQL, используя Hibernate Criteria API - PullRequest
5 голосов
/ 06 марта 2012

Я хочу написать метод, который возвращает список последних добавленных объектов, сгруппированных по полю 'serviceId'.

Следующий HQL работает, но я хочу написать это с помощью Criteria API:

FROM Notification WHERE date IN 
    (SELECT MAX(date) FROM Notification GROUP BY serviceId) 
ORDER BY date ASC

Примерно так:

Criteria crit = session.createCriteria(Notification.class);
crit.add(Restrictions.in("date", <MAX dates>));
criteria.addOrder(Order.desc("date"));

Заранее спасибо.

РЕДАКТИРОВАТЬ:

Теперь мне нужен аналогичный запрос, который работает с использованиемeclipselink API = /
По сути, мне нужны последние N строк (максимальная дата), статус которых является одним из пяти описанных ниже, сгруппированных по столбцу serviceId.
Из-за моей неопытности это было лучшее, что я мог:

ExpressionBuilder builder = new ExpressionBuilder();
Expression exStatus1 = builder.get("status").equal(MessageType.START.toString());
Expression exStatus2 = builder.get("status").equal(MessageType.RUNNING.toString());
Expression exStatus3 = builder.get("status").equal(MessageType.PAUSED.toString());
Expression exStatus4 = builder.get("status").equal(MessageType.END_ERROR.toString());
Expression exStatus5 = builder.get("status").equal(MessageType.END_SUCCESS.toString());

ReadAllQuery query = new ReadAllQuery();
query.setReferenceClass(Notification.class);
query.setSelectionCriteria(((exStatus1).or(exStatus2).or(exStatus3).or(exStatus4).or(exStatus5)));
query.setMaxRows(listSize);
query.addDescendingOrdering("date");

Предложение об избежании дублирования идентификаторов обслуживания в строках результатов отсутствует ...

1 Ответ

4 голосов
/ 06 марта 2012

Вы захотите использовать API проекций Criteria с отдельным подзапросом:

Criteria crit = session.createCriteria(Notification.class, "main");

DetachedCriteria notificationSubQuery = DetachedCriteria.forClass(Notification.class, "sub");
notificationSubQuery.setProjection(Projections.max("date"));
notificationSubQuery.add(Restrictions.eqProperty("sub.serviceId", "main.serviceId"));

crit.add(Subqueries.propertyIn("date", notificationSubQuery));
crit.addOrder(Order.desc("date"));

Это отражает технику, которую вы используете в HQL-запросе.

EDIT

Я обновил запрос, чтобы он соответствовал идентификатору serviceId между вашим основным классом уведомлений и вашим подзапросом, по сути, так же, как этот запрос HQL:

FROM Notification main WHERE date IN 
    (SELECT MAX(sub.date) FROM Notification sub WHERE sub.serviceId = main.serviceId) 
ORDER BY date ASC

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

serviceId = 1: date = 3,4,5
serviceId = 2: date = 4,5,6

Старый запрос возврата:

serviceId: 1, date: 5
serviceId: 2, date: 5,6

Новый запрос возврата:

serviceId: 1, date: 5 
serviceId: 2, date: 6

Дайте мне знать, если это работает для вас.

...