2012-03-06 3 views
5

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

Следующая 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")); 

Спасибо заранее.

EDIT:

Теперь мне нужен подобный запрос, который работает с помощью 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"); 

Предложение, чтобы избежать дубликатов serviceIds в строки результата не хватает ...

ответ

4

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

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 

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

+1

Но OP хочет, чтобы подзапрос был 'select max (date) из группы уведомлений serviceId', вместо этого просто' select max (date) from Notification' –

+0

Моя ошибка, обновлена. –

+0

Прекрасно работает! Благодарю. – elias

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