So führen Sie Datumsoperationen im Ruhezustand durch
Frage
Ich möchte Datenzeitoperationen mit Hibernate HQL durchführen.
Ich möchte zwei Daten addieren und subtrahieren sowie 1 Jahr oder 1 Monat von einem bestimmten Datum subtrahieren.
Wie ist dies mit HQL im Ruhezustand möglich?
Lösung
Siehe Performing Datum / Zeit Math In HQL? für ein Beispiel.
benutzerdefinierte SQL verwenden müssen Sie einen eigenen Hibernate Dialekt geschrieben und registrieren:
registerFunction("weekday",
new SQLFunctionTemplate(Hibernate.INTEGER, "to_char(?1,'D')") );
Andere Tipps
Sie müssen Ihren eigenen Dialekt erstellen. Etwas wie folgt aus:
public class MyDialect extends MySQLInnoDBDialect{
public myDialect() {
super();
registerFunction("date_add_interval", new SQLFunctionTemplate(Hibernate.DATE, "date_add(?1, INTERVAL ?2 ?3)"));
}
}
In Hibernate / MySQL (mindestens) Sie können zu und von einem Unix-Zeitstempel umwandeln. Da der Unix-Zeitstempel eine ganze Zahl ist, können Sie eine ganze Anzahl von Sekunden, um es hinzuzufügen.
FROM_UNIXTIME(UNIX_TIMESTAMP(date)+ (allowedTimeWindow*86400)) as deadline
Es hat seine Grenzen, aber es ist viel einfacher, als die Ansätze oben.
Dies ist eine offene Frage in dem Ruhezustand. Ab Hibernate 3.3 gibt es keine Standardmethode Datum Vergleiche rein in HQL zu behandeln:
https://hibernate.atlassian.net/browse/HHH-2434
4.3 bietet Funktionen Hibernate Datum / Uhrzeit in HQL zuzugreifen, die sind:
current_timestamp() , current_date() , current_time()
können arithmetische Operationen durch verwaltet werden:
SECOND(...) , MINUTE(...) , HOUR(...) , DAY(...) , MONTH(...) , YEAR(...)
Disclaimer: Ich bin ein Java Anfänger
Ich konnte current_date() >= fromDate AND dateadd(day, -1, getdate()) <= toDate
in einer HQL-Anweisung für eine Sybase db in Hibernate 3.5.3, verwenden, ohne Funktionen zu registrieren.
Anwendungsbeispiel des Ansatzes mit Dialekt für JPA + Hibernate 4.3.1 + MySQL 5
public class SampleMySQL5InnoDBDialect erweitert org.hibernate.dialect.MySQL5InnoDBDialect {
public SampleMySQL5InnoDBDialect() {
super();
registerFunction("date_sub_days", new SQLFunctionTemplate(StandardBasicTypes.DATE, "date_sub(?1, interval ?2 day)"));
}
dann für Ihre Klasse mit Mapping-Anmerkung:
@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 hat toDate Feld vom Typ java.sql.Date und Dauer integer-Feld (in Tagen Dauer), und wir sind der Berechnung VonDatum = toDate - Dauer und alle Elemente ausgewählt werden, die VonDatum oder toDate innerhalb Intervall [startdate, endDate] .
Hibernate4.3 bietet native Funktionen, um auf Datums-/Zeitstempel zuzugreifen und arithmatische Operationen darauf durchzuführen
Hier ist der Link zur Dokumentation darüber, welche Ausdrücke in HQL verwendet werden können.Einige davon erwähne ich:So greifen Sie auf Datum/Uhrzeit zu:
current_date(), current_time(), and current_timestamp()
Arithmetische Operationen können wie folgt ausgeführt werden.Diese Funktionen benötigen Zeit als Eingabe:
second(...), minute(...), hour(...), day(...), month(...), and year(...)
Man kann den absoluten Unterschied in HQL ermitteln durch
current_timestamp() - dateInstance
wobei dateInstance eine Definition haben kann
@Column(name = "updated_at")
@Temporal(TemporalType.TIMESTAMP)
private java.util.Date updatedAt;
Das Ergebnis liegt in 0,1 Sekunden vor.Für eine absolute Differenz von 1 Sekunde ergibt der obige Ausdruck also das Ergebnis 10.
Eine Abfrage würde also wie folgt aussehen:
select t from Table t where (current_timestamp() - updatedAt)>600
Posgresbenutzer ...
registerFunction("dateadd", new SQLFunctionTemplate(StandardBasicTypes.DATE, "(?1 + INTERVAL ?2)"));
mit SQL Nutzung wie:
now() < dateadd(:mydate, '-1 day')