Le informazioni complete (ed è più complesso di quanto descritto qui e potrebbe dipendere da quale particolare versione dei driver Oracle è in uso) si trovano nella risposta di Richard Yee qui - [link ora scaduto a Nabble]
Afferra velocemente prima che scada da nabble...
Roger, vedi:http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-faq-090281.html#08_01
In particolare:Tipi di dati sempliciCosa sta succedendo con DATE e TIMESTAMP?Questa sezione riguarda i tipi di dati semplici. :-)
Prima della versione 9.2, i driver Oracle JDBC associavano il tipo SQL DATE a java.sql.Timestamp. Ciò ha avuto un certo senso perché il tipo SQL Oracle DATE contiene informazioni sia sulla data che sull'ora, così come java.sql.Timestamp. La mappatura più ovvia su java.sql.Date era alquanto problematica poiché java.sql.Date non include informazioni sull'ora. Inoltre, RDBMS non supportava il tipo SQL TIMESTAMP, quindi non si sono verificati problemi con la mappatura di DATE in Timestamp.
In 9.2 il supporto TIMESTAMP è stato aggiunto all'RDBMS. La differenza tra DATE e TIMESTAMP è che TIMESTAMP include nanosecondi e DATE no. Quindi, a partire da 9.2, DATE viene mappato su Date e TIMESTAMP su Timestamp. Sfortunatamente, se facevi affidamento sui valori DATE per contenere le informazioni sull'ora, c'è un problema.
Esistono diversi modi per risolvere questo problema:
Modifica le tue tabelle per utilizzare TIMESTAMP invece di DATE. Questo è probabilmente raramente possibile, ma è la soluzione migliore quando lo è.
Modifica la tua applicazione per utilizzare defineColumnType per definire le colonne come TIMESTAMP anziché DATE. Ci sono problemi con questo perché non vuoi davvero usare defineColumnType a meno che non sia necessario (vedi Che cos'è defineColumnType e quando dovrei usarlo?).
Modifica l'applicazione per utilizzare getTimestamp anziché getObject. Questa è una buona soluzione quando possibile, tuttavia molte applicazioni contengono codice generico che si basa su getObject, quindi non è sempre possibile.
Impostare la proprietà di connessione V8Compatible. Questo dice ai driver JDBC di usare la vecchia mappatura piuttosto che quella nuova. È possibile impostare questo flag come proprietà di connessione o come proprietà di sistema. È possibile impostare la proprietà di connessione aggiungendola all'oggetto java.util.Properties passato a DriverManager.getConnection o OracleDataSource.setConnectionProperties. Puoi impostare la proprietà di sistema includendo un'opzione -D nella tua riga di comando java.
java -Doracle.jdbc.V8Compatible="true" MyAppOracle JDBC 11.1 risolve questo problema. A partire da questa versione, il driver esegue il mapping delle colonne SQL DATE a java.sql.Timestamp per impostazione predefinita. Non è necessario impostare V8Compatible per ottenere la mappatura corretta. V8Compatible è fortemente deprecato. Non dovresti usarlo affatto. Se lo imposti su true non farà male a nulla, ma dovresti smettere di usarlo.
Sebbene fosse usato raramente in questo modo, V8Compatible non esisteva per risolvere il problema DATE to Date ma per supportare la compatibilità con i database 8i. I database 8i (e precedenti) non supportavano il tipo TIMESTAMP. L'impostazione di V8Compatible non solo ha causato la mappatura di SQL DATE su Timestamp durante la lettura dal database, ma ha anche causato la conversione di tutti i timestamp in SQL DATE quando scritti nel database. Poiché 8i è desupportato, i driver JDBC 11.1 non supportano questa modalità di compatibilità. Per questo motivo V8Compatible è desupportato.
Come accennato in precedenza, i driver 11.1 per impostazione predefinita convertono SQL DATE in Timestamp durante la lettura dal database. Questa è sempre stata la cosa giusta da fare e il cambio in 9i è stato un errore. I driver 11.1 hanno ripristinato il comportamento corretto. Anche se non hai impostato V8Compatible nella tua applicazione, nella maggior parte dei casi non dovresti vedere alcuna differenza nel comportamento. Potresti notare una differenza se usi getObject per leggere una colonna DATE. Il risultato sarà un timestamp anziché una data. Poiché Timestamp è una sottoclasse di Date, in genere non è un problema. Dove potresti notare una differenza è se hai fatto affidamento sulla conversione da DATE a Date per troncare il componente temporale o se lo fai aString sul valore. In caso contrario, la modifica dovrebbe essere trasparente.
Se per qualche motivo la tua app è molto sensibile a questa modifica e devi semplicemente avere il comportamento 9i-10g, è possibile impostare una proprietà di connessione. Imposta mapDateToTimestamp su false e il driver tornerà al comportamento predefinito 9i-10g e mapperà DATE a Date.
Se possibile, dovresti cambiare il tipo di colonna in TIMESTAMP invece di DATE.
-Riccardo
Roger Voss ha scritto:Ho pubblicato la seguente domanda/problema su StackOverflow, quindi se qualcuno conosce una soluzione, sarebbe bello vedere che rispondesse lì:
Problema di conversione Oracle SQL DATE utilizzando iBATIS tramite Java JDBC
Ecco la descrizione del problema:
Attualmente sto lottando con un problema di conversione Oracle sql DATE utilizzando iBATIS da Java.
Sto usando il thin driver Oracle JDBC ojdbc14 versione 10.2.0.4.0. iBATIS versione 2.3.2. Java 1.6.0_10-rc2-b32.
Il problema ruota attorno a una colonna di tipo DATE che viene restituita da questo frammento di SQL:
SELEZIONA *DA TABELLA(pk_invoice_qry.get_contract_rate(?,?,?,?,?,?,?,?,?,?,?)) ordina entro da_data
La chiamata alla procedura del pacchetto restituisce un cursore di riferimento che viene racchiuso in una TABELLA in cui è quindi facile leggere il set di risultati come se fosse una query di selezione su una tabella.
In PL/SQL Developer, una delle colonne restituite, FROM_DATE, di tipo SQL DATE, ha precisione in base all'ora del giorno:
Tue Dec 16 23:59:00 PST 2008
Ma quando accedo a questo tramite iBATIS e JDBC, il valore mantiene la precisione solo fino al giorno:
Tue Dec 16 12:00:00 AM PST 2008
Questo è più chiaro se visualizzato in questo modo:
Avrebbe dovuto essere:1229500740000 millisecondi da epochmartedì 16 dicembre 2008 23:59:00 PST
Ma ottenendo questo invece:1229414400000 millisecondi da epochMartedì 16 dicembre 2008 00:00:00 PST (come istanza della classe java.sql.Date)
Indipendentemente da ciò che provo, non sono in grado di esporre la piena precisione di questa colonna DATE da restituire tramite Java JDBC e iBATIS.
Ciò da cui iBATIS sta mappando è questo:
FROM_DATE:03-12-2008:classe java.sql.Date
L'attuale mappatura iBATIS è questa:
Ho anche provato:
o
Ma tutti i tentativi di mappatura producono lo stesso valore di data troncato. È come se JDBC avesse già fatto il danno di perdere la precisione dei dati prima ancora che iBATIS li toccasse.
Chiaramente sto perdendo parte della precisione dei miei dati passando attraverso JDBC e iBATIS che non accade quando rimango in PL/SQL Developer eseguendo lo stesso snippet SQL come script di test. Per niente accettabile, molto frustrante e, in definitiva, molto spaventoso.