2010-05-18 13 views
20
SELECT x FROM SomeClass 
WHERE x.dateAtt BETWEEN CURRENT_DATE AND (CURRENT_DATE + 1 MONTH) 

Nella dichiarazione JPQL sopra, SomeClass ha un memebr dateAttr, che è un java.util.Date ed ha un'annotazione @Temporal(javax.persistence.TemporalType.DATE).Java: funzione di data JPQL per aggiungere un periodo di tempo per un'altra data

Ho bisogno di un modo per fare il (CURRENT_DATE + 1 MONTH) bit - è ovviamente sbagliato nel suo stato attuale - ma non riesco a trovare il documento con la funzione di data per JPQL.

Qualcuno può indicarmi in direzione di un documento che i documenti contengano le funzioni di data JPQL (e anche come eseguire questa particolare query)?

+0

Si tratta di una query in qualche metodo che si desidera? O questo deve essere in un trigger sul bean di entità esso stesso? IE: '@ PrePersist' o' @ PreUpdate'? –

+0

@Shervin: No, la query non deve essere eseguita in '@ PrePersist' o' @ PreUpdate'. La query è una query denominata su una classe Entity JPA ('SomeClass'). – bguiz

+0

@Shervin: Inoltre, so che posso usare Java per calcolare le manipolazioni di 'Date' e poi passarlo nella query usando un': parameter', tuttavia, preferirei farlo nello stesso JPQL ed evitare quello non necessario codice. – bguiz

risposta

17

Se si dispone di un oggetto data che è + 1 mese già si potrebbe fare qualcosa di simile:

public List findEmployees(Date endDate) { 
    return entityManager.createQuery(
    "SELECT e from Employee e WHERE e.startDate BETWEEN ?1 AND ?2") 
    .setParameter(1,new Date(), TemporalType.DATE) 
    .setParameter(2,endDate, TemporalType.DATE).getResultList(); 
} 

Questo, tuttavia, richiede che le date siano valide prima mano.

UPDATE

Se si vuole sempre il mese successivo, è possibile utilizzare JodaTime che ha una grande e facile api. È quindi possibile modificare la query in questo modo:

//Get next month 
DateTime dt = new DateTime(); 
entityManager.createQuery(
"SELECT e from Employee e WHERE e.startDate BETWEEN ?1 AND ?2") 
.setParameter(1,new Date(), TemporalType.DATE) 
.setParameter(2,dt.plusMonths(1).toDate(), TemporalType.DATE).getResultList(); 
+3

Hai provato la parte JodaTime? JPA può trattare con un 'DateTime'? –

+0

@Pascal: buon punto.Ho dimenticato il metodo toDate(). Questo restituirà un 'java.util.Date' –

+1

Miglioramento leggero:' .setParameter (1, dt.toDate(), TemporalType.DATE) '(una importazione di meno e coerenza con la riga successiva) –

4

o utilizzare commons-lang invece di jodatime:

entityManager.createQuery(
    "SELECT e from Employee e WHERE e.startDate BETWEEN ?1 AND ?2" 
) 
.setParameter(1,new Date(), TemporalType.DATE) 
.setParameter(2,DateUtils.addMonths(new Date(), 1), TemporalType.DATE) 
.getResultList(); 

Ma so che questo non è quello che chiedete e io sono abbastanza sicuro che non può essere fatto in JPQL da solo, dovrai passare un parametro o utilizzare una query con nome nativo

+0

'DateUtils'? È quella parte di JDK std o è una libreria come l'ora di Joda? – bguiz

+0

è in apache commons/lang, una libreria open source utilizzata internamente da molti framework: http://commons.apache.org/lang/ –

+2

Meglio usare Joda-Time perché è un'implementazione di riferimento di JSR-310 (https : //jsr-310.dev.java.net/) –

15

JPQL standard non supporta tali operazioni in date. Dovrai utilizzare una query nativa o eseguire il calcolo sul lato Java.

+1

È ancora vero? – span

0

Dears,

sto usando i dati di primavera, l'entità salvare il createdDate come datetime, e nel repository così:

@Query(value="SELECT t FROM MyEntity t WHERE t.createdDate Between ?1 and ?2") 
public List<MyEntity> findAllBetweenDates(Calendar from, Calendar to); 

quindi non posso usare:

setParameter(1,new Date(), TemporalType.DATE 

nel chicco backend Io uso il seguente:

//to set zero of hours,minutes,seconds and milliseconds 
    fromCalendar.set(java.util.Calendar.HOUR, 0); 
    fromCalendar.set(java.util.Calendar.MINUTE, 0); 
    fromCalendar.set(java.util.Calendar.SECOND, 0); 
    fromCalendar.set(java.util.Calendar.MILLISECOND, 0); 

    toCalendar.set(java.util.Calendar.HOUR, 0); 
    toCalendar.set(java.util.Calendar.MINUTE, 0); 
    toCalendar.set(java.util.Calendar.SECOND, 0); 
    toCalendar.set(java.util.Calendar.MILLISECOND, 0); 
    // add 1 days and decrease 1 millisecond 
    toCalendar.add(java.util.Calendar.DAY_OF_MONTH, 1); 
    toCalendar.add(java.util.Calendar.MILLISECOND, -1); 

    allEntities = myEntityRepository.findAllBetweenDates(fromCalendar, toCalendar); 
} 

e funziona bene.

Problemi correlati