2009-03-12 8 views
16

Je cherche à effectuer des calculs de date/heure dans une requête HQL. Plus précisément, comment ajouter ou soustraire (x) la quantité de temps du résultat de la fonction current_timestamp()? Ou dois-je passer dans SQL pour cela et espérer que quelle que soit la base de données en cours d'exécution le supporte?Performing Date/Heure Maths en HQL?

exemple de requête HQL:

FROM RandomThing 
WHERE randomTime IS NOT NULL AND 
     randomTime >= current_timestamp() AND 
     randomTime <= (current_timestamp() + :timeToAdd) 

je peux définir le: paramètre timeToSubtract être une unité particulière, bien que quoi que ce soit plus que les heures ne serait pas souhaitable, et secondes serait plus souhaitable. CLARIFICATION: Je réalise que cela peut être facilement fait en dehors de la requête. Mais pour des raisons philosophiques, disons qu'il est important d'utiliser l'heure du serveur de base de données, plutôt que l'heure du système d'interrogation. Exemple pratique: j'interroge un horodatage automatique pour toutes les entrées effectuées au cours de la dernière période (x). Comme l'horodatage est effectué par le système de base de données, il est important d'utiliser également l'heure actuelle de la base de données.

+0

Je cherche aussi la même chose, sauf que timeToAdd n'est pas un paramètre, mais une colonne de la même ligne, donc cela n'a pas de sens d'effectuer une seconde requête sur la même ligne et la même table. – James

Répondre

3

Si vous avez besoin de temps du serveur de base de données, vous pourriez d'abord faire une simple requête HQL pour obtenir l'horodatage, puis calculer la maxTimestamp en java et passer le tiré par les cheveux timestamp et maxTimeStamp calculé pour une requête comme celle de ccclark.

+0

Je pense que c'est la solution la plus généralisable et la plus facile à implémenter. Merci. – jdmichal

10

Pourquoi avez-vous besoin de le faire dans la requête? Pourquoi ne pas le gérer dans le code java?

par exemple:

From RandomThing 
Where randomTime is not null and 
     randomTime >= :currentTimestamp and 
     randomTime <= :maxTimestamp 

Et puis définissez simplement les paramètres.

+0

Bonne réponse. J'ai apporté des éclaircissements à la question avec ma réponse. – jdmichal

+2

Parce que le code Java peut ne pas s'exécuter sur la même horloge, et dans certaines requêtes, même une différence de quelques secondes peut causer des problèmes. – Quartz

4

Vous pouvez déterminer la syntaxe pour le faire en utilisant SQL dans votre base de données, puis définir une fonction dans un HibernateDialect personnalisé. Par exemple, nous avions besoin d'une fonction de jour qui n'est pas standard SQL. Nous subclassed le dialecte pour chaque base de données, puis ajouté une ligne comme celui-ci:

registerFunction("weekday", 
    new SQLFunctionTemplate(Hibernate.INTEGER, "to_char(?1,'D')")); 

Dans votre cas, vous pouvez utiliser une fonction appelée date_diff qui pourrait être défini comme? -? dans certaines bases de données ou quelque chose de différent dans d'autres. De cette façon, vous n'avez pas besoin d'écrire du SQL brut dans votre requête et si vous avez besoin de changer de base de données, il vous suffit de mapper la fonction différemment dans votre dialecte.

1

Est-ce que ce doit être HQL? Je serais probablement passer à un critère de mise en veille prolongée et utilisation:

Criteria.add(Restrictions.SQLRestriction("{alias} <= current_timestamp() ")) 
Criteria.add(Restrictions.SQLRestriction("{alias} >= (current_timestamp() + ?) ", 5) 
+1

Quelle est la différence entre mettre ces deux instructions dans les critères par rapport à une requête HQL? – jdmichal

+0

Cette solution fonctionne avec l'API CriteriaQuery, ce qui est utile si l'on suit déjà cette approche. –