Come fare un confronto timestamp con Query JPA?
Domanda
Abbiamo bisogno di assicurarsi che solo i risultati negli ultimi 30 giorni vengono restituiti per una query JPQL. Segue un esempio:
Date now = new Date();
Timestamp thirtyDaysAgo = new Timestamp(now.getTime() - 86400000*30);
Query query = em.createQuery(
"SELECT msg FROM Message msg "+
"WHERE msg.targetTime < CURRENT_TIMESTAMP AND msg.targetTime > {ts, '"+thirtyDaysAgo+"'}");
List result = query.getResultList();
Ecco l'errore che riceviamo:
<openjpa-1.2.3-SNAPSHOT-r422266:907835 nonfatal user error> org.apache.openjpa.persistence.ArgumentException: An error occurred while parsing the query filter 'SELECT msg FROM BroadcastMessage msg WHERE msg.targetTime < CURRENT_TIMESTAMP AND msg.targetTime > {ts, '2010-04-18 04:15:37.827'}'. Error message: org.apache.openjpa.kernel.jpql.TokenMgrError: Lexical error at line 1, column 217. Encountered: "{" (123), after : ""
Aiuto!
Soluzione
Quindi, la query di input non è JPQL (che si poteva vedere facendo riferimento alle specifiche JPA). Se si desidera confrontare un campo con una data poi si immette la data come un parametro per la query
msg.targetTime < CURRENT_TIMESTAMP AND msg.targetTime > :param
QUESTO NON E 'SQL.
Altri suggerimenti
La sintassi di fuga JDBC potrebbe non essere supportato nella versione di OpenJPA che si sta utilizzando. La documentazione per l'ultima versione 1.2.x è qui: http://openjpa.apache.org/builds/1.2.2/apache-openjpa-1.2.2/docs/manual/manual.html#jpa_langref_lit .
La documentazione di cui in precedenza si riferisce ai documenti per OpenJPA 2.0.0 (l'ultima): http://openjpa.apache.org/builds/latest/docs/manual/jpa_langref.html#jpa_langref_lit
Detto questo v'è alcuna ragione perché si vuole iniettare una stringa nella vostra JPQL? Che dire qualcosa di simile al seguente frammento?
Date now = new Date();
Date thirtyDaysAgo = new Date(now.getTime() - (30 * MS_IN_DAY));
Query q = em.createQuery("Select m from Message m "
+ "where m.targetTime < :now and m.targetTime > :thirtyDays");
q.setParameter("now", now);
q.setParameter("thirtyDays", thirtyDaysAgo);
List<Message> results = (List<Message>) q.getResultList();