Den fulde information (og den er mere kompleks end beskrevet her og kan afhænge af, hvilken bestemt version af Oracle-driverne der er i brug) er i Richard Yees svar her - [nu udløbet link til Nabble]
Hurtig fat, før den udløber fra nabble...
Roger, se:http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-faq-090281.html#08_01
Specifikt:Simple datatyperHvad sker der med DATO og TIDSTAMP? Dette afsnit handler om simple datatyper. :-)
Før 9.2 tilknyttede Oracle JDBC-driverne DATE SQL-typen til java.sql.Timestamp. Dette gav en vis mening, fordi Oracle DATE SQL-typen indeholder både dato- og tidsoplysninger, ligesom java.sql.Timestamp. Den mere indlysende tilknytning til java.sql.Date var noget problematisk, da java.sql.Date ikke inkluderer tidsoplysninger. Det var også sådan, at RDBMS ikke understøttede TIMESTAMP SQL-typen, så der var ingen problemer med at tilknytte DATE til Timestamp.
I 9.2 blev TIMESTAMP-understøttelse tilføjet til RDBMS. Forskellen mellem DATE og TIMESTAMP er, at TIMESTAMP inkluderer nanosekunder og DATE ikke. Så begyndende i 9.2 er DATE kortlagt til Dato og TIMESTAMP er kortlagt til Timestamp. Desværre er der et problem, hvis du stolede på DATE-værdier for at indeholde tidsoplysninger.
Der er flere måder at løse dette problem på:
Skift dine tabeller til at bruge TIMESTAMP i stedet for DATE. Dette er nok sjældent muligt, men det er den bedste løsning, når det er tilfældet.
Skift din applikation til at bruge defineColumnType til at definere kolonnerne som TIMESTAMP i stedet for DATE. Der er problemer med dette, fordi du virkelig ikke ønsker at bruge defineColumnType, medmindre du er nødt til det (se Hvad er defineColumnType, og hvornår skal jeg bruge det?).
Ændr dit program til at bruge getTimestamp i stedet for getObject. Dette er en god løsning, når det er muligt, men mange applikationer indeholder generisk kode, der er afhængig af getObject, så det er ikke altid muligt.
Indstil egenskaben V8Compatible forbindelse. Dette fortæller JDBC-driverne at bruge den gamle kortlægning i stedet for den nye. Du kan indstille dette flag enten som en forbindelsesegenskab eller en systemegenskab. Du indstiller forbindelsesegenskaben ved at føje den til java.util.Properties-objektet, der er sendt til DriverManager.getConnection eller til OracleDataSource.setConnectionProperties. Du indstiller systemegenskaben ved at inkludere en -D-indstilling i din java-kommandolinje.
java -Doracle.jdbc.V8Compatible="true" MyAppOracle JDBC 11.1 løser dette problem. Fra og med denne udgivelse knytter driveren SQL DATE-kolonner til java.sql.Timestamp som standard. Der er ingen grund til at indstille V8Compatible for at få den korrekte kortlægning. V8Compatible er stærkt forældet. Du bør slet ikke bruge det. Hvis du sætter det til sandt, skader det ikke noget, men du bør stoppe med at bruge det.
Selvom det sjældent blev brugt på den måde, eksisterede V8Compatible ikke for at løse problemet med DATE til dato, men for at understøtte kompatibilitet med 8i-databaser. 8i (og ældre) databaser understøttede ikke TIMESTAMP-typen. Indstilling af V8Compatible medførte ikke kun, at SQL DATE blev mappet til Timestamp, når de blev læst fra databasen, det forårsagede også, at alle Timestamps blev konverteret til SQL DATE, når de blev skrevet til databasen. Da 8i ikke understøttes, understøtter 11.1 JDBC-driverne ikke denne kompatibilitetstilstand. Af denne grund er V8Compatible ikke understøttet.
Som nævnt ovenfor konverterer 11.1-driverne som standard SQL DATE til Timestamp, når de læser fra databasen. Dette har altid været den rigtige ting at gøre, og ændringen i 9i var en fejl. 11.1-chaufførerne er vendt tilbage til den korrekte adfærd. Selvom du ikke har indstillet V8Compatible i din applikation, bør du i de fleste tilfælde ikke se nogen forskel i adfærd. Du vil muligvis bemærke en forskel, hvis du bruger getObject til at læse en DATE-kolonne. Resultatet vil være et tidsstempel i stedet for en dato. Da Timestamp er en underklasse af Date, er dette generelt ikke et problem. Hvor du måske bemærker en forskel, er, hvis du stolede på konverteringen fra DATE til Date for at afkorte tidskomponenten, eller hvis du gør toString på værdien. Ellers bør ændringen være gennemsigtig.
Hvis din app af en eller anden grund er meget følsom over for denne ændring, og du blot skal have 9i-10g-adfærden, er der en forbindelsesegenskab, du kan indstille. Indstil mapDateToTimestamp til false, og driveren vil vende tilbage til standard 9i-10g-adfærden og kortlægge DATE til Dato.
Hvis det er muligt, bør du ændre din kolonnetype til TIMESTAMP i stedet for DATE.
-Richard
Roger Voss skrev:Jeg postede følgende spørgsmål/problem om stackoverflow, så hvis nogen kender en løsning, ville det være godt at se det besvaret der:
Oracle SQL DATE-konverteringsproblem ved brug af iBATIS via Java JDBC
Her er problembeskrivelsen:
Jeg kæmper i øjeblikket med et Oracle sql DATE-konverteringsproblem ved hjælp af iBATIS fra Java.
Jeg bruger Oracle JDBC tynde driver ojdbc14 version 10.2.0.4.0. iBATIS version 2.3.2. Java 1.6.0_10-rc2-b32.
Problemet drejer sig om en kolonne af typen DATE, der returneres af dette uddrag af SQL:
VÆLG *FRA TABEL(pk_invoice_qry.get_contract_rate(?,?,?,?,?,?,?,?,?,?)) bestil inden fra_dato
Pakkeprocedurekaldet returnerer en ref-markør, der er ved at blive pakket ind i en TABEL, hvortil det er let at læse resultatsættet, som om det var en udvalgt forespørgsel mod en tabel.
I PL/SQL Developer har en af de returnerede kolonner, FROM_DATE, af SQL DATE-typen, præcision i forhold til tidspunktet på dagen:
Tue Dec 16 23:59:00 PST 2008
Men når jeg får adgang til dette via iBATIS og JDBC, bevarer værdien kun præcisionen i dag:
Tue Dec 16 12:00:00 AM PST 2008
Dette er tydeligere, når det vises sådan:
Skulle have været:1229500740000 millisekunder siden epokeTirsdag den 16. december 2008 23:59:00 PST
Men får dette i stedet:1229414400000 millisekunder siden epochTuesday, December 16, 2008 12:00:00 AM PST(som instans af klassen java.sql.Date)
Uanset hvad jeg prøver, er jeg ikke i stand til at afsløre den fulde præcision af denne DATE-kolonne, der skal returneres via Java JDBC og iBATIS.
Hvad iBATIS kortlægger fra er dette:
FROM_DATE:2008-12-03:class java.sql.Date
Den aktuelle iBATIS-kortlægning er denne:
Jeg har også prøvet:
eller
Men alle forsøgte tilknytninger giver den samme trunkerede Dato-værdi. Det er, som om JDBC allerede har gjort skaden ved at miste datapræcision, før iBATIS overhovedet rører ved den.
Det er klart, at jeg mister noget af min datapræcision ved at gå gennem JDBC og iBATIS, hvilket ikke sker, når jeg bliver i PL/SQL Developer og kører det samme SQL-uddrag som et testscript. Slet ikke acceptabelt, meget frustrerende og i sidste ende meget skræmmende.