2009-06-11 6 views
15

Ho una tabella (in Oracle 9 e successive) in cui è necessario trovare tutte le voci per un determinato giorno utilizzando Hibernate. Le voci hanno data/ora (con tipo di dati 'data'). Alcune voci hanno un tempo, altre hanno solo una data. Questo non può essere modificato, poiché questo è l'output di altre applicazioni che non posso modificare. In SQL vorrei scrivere qualcosa sulla falsariga diUtilizzo di HQL per eseguire una query in una data ignorando l'ora su Oracle

SELECT * FROM table WHERE trim(table.date) = to_date('11.06.2009') 

per ottenere tutte le voci per la data che sto cercando. Mi stavo chiedendo come ottenere Hibernate per farlo usando HQL. So che posso usare SQL-query in Hibernate, ma questo sembra essere meno pulito. C'è un modo per fare questo? Se possibile, questo metodo dovrebbe funzionare anche su database non Oracle dove il timestamp sarebbe il tipo di dati.

risposta

14

È possibile inserire due vincoli nell'HQL, uno che specifica maggiore o uguale all'inizio della data in cui si sta effettuando la ricerca e uno che specifica meno del giorno successivo.

cioè

table.date >=11.06.2009 AND table.date < 11.07.2009 

HQL (così come SQL) consente inoltre di:

table.date between 11.06.2009 AND 11.07.2009 

Tenete a mente between è sempre inclusivo, che significa che è, rispettivamente, sia >= e <=.
Maggiori dettagli su between qui: http://www.coding-dude.com/wp/java/hibernate-java/hibernate-hql-between-expression/

2

penso che ci sono due modi per risolvere questo:

  1. utilizzare una query criteria e aggiungere un SQLRestriction. La restrizione assumerebbe la forma "trim ({alias} .date) =?". Un problema qui potrebbe essere la conversione del parametro di input nel tipo corretto su Oracle (o altro DBMS). È possibile fornire il parametro necessario (sospensione) come parametro, ma se questo è dipendente dal database, verrà codificato come hardcoded.

  2. utilizzare uno formula nella mappatura di ibernazione. La mappatura sarebbe:

 <class name="Person"> 
     <property name="birthDay" formula="trim(birthDay)"/> 
    </class>

È ora possibile utilizzare il sistema di digitazione di Hibernate utilizzare un confronto con un oggetto Java come questo:

s.createCriteria(Person.class) 
.add(Restrictions.eq("birthDay", new java.sql.Date(System.currentTimeMillis()))) 
.list() 

Un problema che avrete con entrambe le soluzioni è la funzione trim potrebbe non essere disponibile nel database. Una soluzione per questo (ad es. Durante il test su HSQLDB) consiste nel mettere un import.sql nel test del classpath (questo verrà prelevato automaticamente da Hibernate) e creare lì una procedura o una funzione. Puoi anche Alter table Person add column birthDay timestamp in quel file per far funzionare lo schema generato.

-1

è possibile utilizzare la funzione trunc() per rimuovere la parte dell'ora nella colonna DATE.

esempio: select * from emp where trunc(emp_date) < trunc(current_date()-30)

recupera tutti i dettagli dei dipendenti che sono stati impiegati 1 mese prima

+8

e se è febbraio? – Setori

+0

Non è una buona idea lavorare con valori costanti, così come ha detto Setori, ci sono mesi con meno di 30 giorni e altri con 31 giorni. – will824

2

Per CustomHQL, si può provare il trunc parola chiave

Per Es:

SELECT T0.FirstName as FirstName ,T0.LastLoginDate as LastLoginDate FROM User T0 
WHERE (trunc(T0.LastLoginDate) >= :LastLoginDate) ORDER BY T0.LastLoginDate 

NOTA: Dove :LastLoginDate è un parametro.

Questo è il trucco per me.