Domanda

Voglio eseguire operazioni temporali sui dati utilizzando l'ibernazione HQL.

Voglio aggiungere e sottrarre due date e voglio sottrarre 1 anno o 1 mese da una data particolare.

Come è possibile utilizzare HQL in ibernazione?

È stato utile?

Soluzione

Vedere Esecuzione di data / ora matematica in HQL? per un esempio.

Per usare sql personalizzato è necessario scrivere un proprio dialetto ibernato e registrarsi:

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

Altri suggerimenti

Devi creare il tuo dialetto. Qualcosa di simile al seguente:

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 (almeno) È possibile convertire da e verso un timestamp Unix. Poiché il timestamp unix è un numero intero, è possibile aggiungere un numero intero di secondi ad esso.

FROM_UNIXTIME(UNIX_TIMESTAMP(date)+ (allowedTimeWindow*86400)) as deadline

Ha dei limiti ma è molto più semplice degli approcci sopra.

Questo è un problema aperto in Hibernate. A partire da Hibernate 3.3 non esiste un modo standard per gestire i confronti di date puramente in HQL:

https://hibernate.atlassian.net/browse/HHH-2434

Hibernate 4.3 offre funzioni per accedere a Data / Ora in HQL che sono:

current_timestamp() , current_date() , current_time()

Le operazioni aritmetiche possono essere gestite da:

SECOND(...) , MINUTE(...) , HOUR(...) , DAY(...) , MONTH(...) , YEAR(...)

Disclaimer: sono un novizio di Java

Sono stato in grado di utilizzare current_date() >= fromDate AND dateadd(day, -1, getdate()) <= toDate in un'istruzione HQL contro un db Sybase in Hibernate 3.5.3, senza registrare alcuna funzione.

Esempio di utilizzo dell'approccio con dialetto per JPA + Hibernate 4.3.1 + MySQL 5

SampleMySQL5InnoDBDialect di classe pubblica estende org.hibernate.dialect.MySQL5InnoDBDialect {

public SampleMySQL5InnoDBDialect() {
    super();
    registerFunction("date_sub_days", new SQLFunctionTemplate(StandardBasicTypes.DATE, "date_sub(?1, interval ?2 day)"));
}

quindi per la tua classe con l'annotazione della mappatura:

@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 ha toDate campo di tipo java.sql.Date e durata campo intero (durata in giorni) e stiamo calcolando fromDate = toDate - duration e selezionando tutte le entità che hanno fromDate o toDate all'interno dell'intervallo [startDate, endDate] .

Hibernate4.3 fornisce funzioni native per accedere a Date / Timestamp e per eseguire operazioni aritmiche su di esse

Qui è il collegamento alla documentazione di quali espressioni possono essere utilizzate in HQL. Pochi dei quali sto citando: Per accedere a data / ora:

current_date(), current_time(), and current_timestamp()

Le operazioni aritmetiche possono essere eseguite come segue. Queste funzioni richiedono tempo come input:

second(...), minute(...), hour(...), day(...), month(...), and year(...)

Si può ottenere la differenza assoluta di in HQL di

current_timestamp() - dateInstance

dove dateInstance può avere una definizione

@Column(name = "updated_at")
@Temporal(TemporalType.TIMESTAMP)
private java.util.Date updatedAt;

Il risultato è in 0,1 secondi. Quindi, per una differenza assoluta di 1 secondo, l'espressione precedente darà il risultato come 10.

Quindi una query sarebbe simile a:

select t from Table t where (current_timestamp() - updatedAt)>600

Utenti Postgres ...

registerFunction("dateadd", new SQLFunctionTemplate(StandardBasicTypes.DATE, "(?1 + INTERVAL ?2)"));

con utilizzo di SQL come:

now() < dateadd(:mydate, '-1 day')
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top