2012-03-06 10 views
5

Desidero scrivere un metodo che restituisca un elenco degli ultimi oggetti aggiunti raggruppati per campo "ID di servizio".Scrittura della clausola HQL utilizzando l'API di Hibernate Criteria

Di seguito HQL funziona, ma voglio scrivere questo utilizzando Criteri API:

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

Qualcosa di simile a questo:

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

Grazie in anticipo.

EDIT:

Ora bisogno di una query simile che lavora utilizzando EclipseLink API =/
Fondamentalmente, ho bisogno dell'ultimo N righe (data max), che lo stato è uno dei cinque descritto più sotto, raggruppato per colonna serviceId.
A causa della mia inesperienza, era il meglio che potevo:

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 clausola per evitare duplicati serviceIds in righe di risultato che manca ...

risposta

4

Stai andando a voler utilizzare le proiezioni Criteri API con sottoquery staccato:

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

Questo rispecchia la tecnica che si sta utilizzando nella query HQL.

EDIT:

ho aggiornato la query in modo che corrisponda ServiceID tra la classe principale di notifica e la tua domanda secondaria, essenzialmente lo stesso di questo HQL Query:

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

questo modo si evita il caso in cui si dovrebbe avere una corrispondenza di data non massima tra due diversi ServiceIds in questo modo:

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

Vecchia query di ritorno :

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

Nuovo ritorno query:

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

Fammi sapere se questo funziona per voi.

+1

Ma OP vuole che la sottoquery sia 'selezionare max (data) dal gruppo di notifica per serviceId', invece solo' selezionare max (data) da Notifica –

+0

Errore, aggiornato. –

+0

Funziona bene! Grazie. – elias

Problemi correlati