Вы захотите использовать 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
Дайте мне знать, если это работает для вас.