2012-03-06 24 views
5

Quiero escribir un método que devuelva una lista de los últimos objetos añadidos agrupados por el campo 'serviceId'.Escribir la cláusula HQL utilizando Hibernate Criteria API

El siguiente HQL funciona, pero yo quiero escribir esto usando los criterios del API:

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

Algo como esto:

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

Gracias de antemano.

EDIT:

Ahora necesito una consulta similar que funciona usando EclipseLink API =/
Básicamente, necesito la última N filas (fecha max), que el estado es uno de los cinco descritos abajo, agrupados por columna serviceId.
Debido a mi inexperiencia, fue lo mejor que pude:

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"); 

La cláusula para evitar duplicados serviceIds en filas de resultados no se encuentra ...

Respuesta

4

Vas a querer usar las proyecciones Criterios API con una subconsulta separada:

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")); 

Esto refleja la técnica que está utilizando en su consulta HQL.

EDITAR:

que actualiza la consulta para que coincida con serviceId entre su clase principal de notificación y su sub consulta, esencialmente el mismo que este HQL Consulta:

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

Esto evita que el caso en el que se tendría una coincidencia de fecha no máxima entre dos diferentes serviceIds como así:

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

Vieja consulta de retorno :

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

Nueva retorno de consulta:

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

Avísame si esto funciona para usted.

+1

Pero OP quiere que la subconsulta sea 'select max (date) from Grupo de notificaciones por serviceId', en su lugar simplemente' select max (date) from Notification' –

+0

Mi error, actualizado. –

+0

¡Funciona bien! Gracias. – elias

Cuestiones relacionadas