Je souhaite effectuer des opérations de temps de données en utilisant hibernate HQL.
Je veux ajouter et soustraire deux dates ainsi que je veux soustraire 1 an ou 1 mois d'une date donnée.
Comment est-ce possible d'utiliser HQL en veille prolongée?
Voir Calculs date/heure dans HQL? à titre d'exemple.
Pour utiliser sql personnalisé, vous devez écrire votre propre dialecte de veille prolongée et vous enregistrer:
registerFunction("weekday",
new SQLFunctionTemplate(Hibernate.INTEGER, "to_char(?1,'D')") );
Vous devez créer votre propre dialecte. Quelque chose comme ce qui suit:
public class MyDialect extends MySQLInnoDBDialect{
public myDialect() {
super();
registerFunction("date_add_interval", new SQLFunctionTemplate(Hibernate.DATE, "date_add(?1, INTERVAL ?2 ?3)"));
}
}
C'est un problème en suspens dans Hibernate. Depuis Hibernate 3.3, il n’existait aucun moyen standard de gérer les comparaisons de dates uniquement en HQL:
https://hibernate.atlassian.net/browse/HHHH2434
Hibernate 4.3 offre des fonctions pour accéder à la date/heure dans HQL, à savoir:
current_timestamp() , current_date() , current_time()
Les opérations arithmétiques peuvent être gérées par:
SECOND(...) , MINUTE(...) , HOUR(...) , DAY(...) , MONTH(...) , YEAR(...)
Dans Hibernate/MySQL (au moins) Vous pouvez convertir vers et depuis un horodatage Unix. Puisque l'horodatage Unix est un entier, vous pouvez lui ajouter un nombre entier de secondes.
FROM_UNIXTIME(UNIX_TIMESTAMP(date)+ (allowedTimeWindow*86400)) as deadline
Il a des limites mais c'est beaucoup plus facile que les approches ci-dessus.
Disclaimer: Je suis un novice Java
J'ai pu utiliser current_date() >= fromDate AND dateadd(day, -1, getdate()) <= toDate
dans une instruction HQL par rapport à une base de données Sybase dans Hibernate 3.5.3, sans enregistrer de fonction.
Exemple d'utilisation de l'approche avec dialecte pour JPA + Hibernate 4.3.1 + MySQL 5
la classe publique SampleMySQL5InnoDBDialect étend org.hibernate.dialect.MySQL5InnoDBDialect {
public SampleMySQL5InnoDBDialect() {
super();
registerFunction("date_sub_days", new SQLFunctionTemplate(StandardBasicTypes.DATE, "date_sub(?1, interval ?2 day)"));
}
puis pour votre classe avec l'annotation de mappage:
@NamedQuery(name = "SampleEntity.getSampleEntitiesForGapOverlapCalculations", query = "from SampleEntity as se where "
+ "((se.toDate between :startDate and :endDate) or (date_sub_days(se.toDate, se.duration) between :startDate and :endDate)) order by se.toDate asc, se.duration desc")
SampleEntity possède toDate champ de type Java.sql.Date et durée champ entier (durée en jours) et nous calculons fromDate = toDate - duration et sélectionnons toutes les entités qui ont fromDate ou toDate à l'intérieur de l'intervalle [date de début, date de fin] .
Les utilisateurs de Postgres ...
registerFunction("dateadd", new SQLFunctionTemplate(StandardBasicTypes.DATE, "(?1 + INTERVAL ?2)"));
avec l'utilisation de SQL comme:
now() < dateadd(:mydate, '-1 day')
Hibernate4.3 fournit des fonctions natives pour accéder aux dates et aux horodatages et y effectuer des opérations arithmatiques.
Ici est le lien vers la documentation des expressions pouvant être utilisées dans HQL. Peu de choses dont je parle: Pour accéder à la date/heure:
current_date(), current_time(), and current_timestamp()
Les opérations arithmétiques peuvent être effectuées en suivant. Ces fonctions prennent le temps en entrée:
second(...), minute(...), hour(...), day(...), month(...), and year(...)
On peut obtenir une différence absolue en HQL par
current_timestamp() - dateInstance
où dateInstance peut avoir une définition
@Column(name = "updated_at")
@Temporal(TemporalType.TIMESTAMP)
private Java.util.Date updatedAt;
Le résultat est dans 0.1 secondes. Donc, pour une différence absolue de 1 seconde, l'expression ci-dessus donnera un résultat égal à 10.
Donc, une requête ressemblerait à ceci:
select t from Table t where (current_timestamp() - updatedAt)>600