2012-07-02 9 views
19

Sto utilizzando Java JDBC per scrivere una data su SQL Server 2008 e quindi leggerlo di nuovo.
La data come letto è sempre due giorni prima della data scritta.date in modo coerente due giorni di riposo

Sto inserendo la riga contenente il campo Data con una dichiarazione preparata. Il valore della data è fornita da:

java.sql.Date todaysDate = new java.sql.Date(System.currentTimeMillis()) ; 
System.out.println(todaysDate.toString()) -> 2012-07-02 
ps.setDate(8, todaysDate); 

Dopo aver scritto la data al db, sql server mi mostra la data corretta se corro:

select date from table_name where date!=null ->2012-07-02 

Se eseguo la stessa query tramite JDBC quindi recuperare il valore data dal gruppo di risultati utilizzando

java.sql.Date sqlDate = rs.getDate("date") ; 
sqlDate.toString() ->2012-06-30 

la riga inserita è l'unica riga nella tabella con data non nullo quindi questo non sembra essere un caso di lettura del record errato.

Ho pensato che si trattasse di un problema ben noto, ma l'unico riferimento che ho trovato da una ricerca su Google per un problema di "due giorni di riposo" non ha avuto una risposta definitiva.

Qualche idea?

beeky (vivere nel passato)

+0

Se si utilizza preparedStatement, non eseguire la conversione da o su String. Passa un oggetto data (o Timestamp) a setDate. –

+0

Quali sono i fusi orari del server e del client? –

+0

Sei sicuro che questo non ha nulla a che fare con MM-DD-YYYY vs DD-MM-YYYY? Se le tue date vanno da e verso le stringhe, possono essere reinterpretate dalle impostazioni locali in modi interessanti e inaspettati (nel runtime del client e nelle librerie del database e nel codice del database). –

risposta

16

difettoso driver JDBC

Si scopre che il problema è stato il pilota MS JDBC. Ho provato ogni possibile combinazione di tipi di date e conversioni di date e niente ha funzionato. Dopo una grande quantità di ricerche (avrei dovuto farlo prima!) Ho visto un commento su una voce SO più vecchia che implicava il problema era il driver jdbc di versione 3 di Microsoft. Ho avuto l'ultimo driver, versione 4.qualcosa, e il problema è andato via.

Grazie a tutto ciò che ha cercato di aiutare. Un ringraziamento speciale a te, Mike, per aver dedicato del tempo a pubblicare una soluzione. - = beeky

+0

È interessante, ma ho riscontrato lo stesso problema anche con friggitrice Microsft JSBC 4, JTDS funziona correttamente – D0dger

0

Il tuo problema è valori fuso orario ("GMT").
È necessario introdurre questa manipolazione nel vostro JDBC metodo di recupero come segue:

Calendar gmt = Calendar.getInstance(TimeZone.getTimeZone("GMT")); 
PreparedStatement stmt = connection.prepareStatement(sql); 
stmt.setDate(1, new Date(0)); // I assume this is always GMT 
ResultSet rs = stmt.executeQuery(); 
rs.next(); 

//This will output 0 as expected 
System.out.println(rs.getDate(1, gmt).getTime()); 
+0

In che modo TZ causerebbe una differenza di due giorni? Posso vedere un giorno vicino alla linea internazionale della data, ma due? –

+0

Mike, il tuo esempio è stato la risposta alla mia domanda o una dimostrazione di come vedere l'offset del fuso orario? – user903724

+0

Hai provato questo e non ha funzionato? – GingerHead

0

Ho avuto esattamente lo stesso problema. L'offset di 2 giorni è andato via non appena ho usato java 6 ambiente di runtime invece di un ambiente di runtime java 7.

Quindi è probabilmente anche una differenza tra la compatibilità con la versione precedente di JDBC versione 4.1 con i driver JDBC 3.

1

Ho incontrato questo problema un paio di volte di recente e mi sono strappato i capelli prima di ricordare che se il campo è di tipo data ciò accade, cambiando il tipo di campo per digitare datetime risolve il problema.

0

come quello che user903724 detto, passare alla versione 4, che sarebbe stato riparato, ma nel mio caso, quando sto usando sqljdbc4-3.0.jar, questo problema riproduce ancora, ma lo cambio a sqljdbc42.jar, questo problema è stato corretto Spero che la mia esperienza sarebbe utile. download da sqljdbc42.jar

0

Ho avuto lo stesso esatto problema anche utilizzando sqljdbc4 con Java 8.

Una volta che non ho bisogno di questo campo per effettuare alcun tipo di confronto nell'applicazione ho risolto il problema colando il campo nella mia domanda in questo modo: CAST(dbo.tblPwActividadeParticipanteDetalhe.Data AS VARCHAR(10)).

2

Per coloro che utilizzano Maven, utilizzare questo per Java 8:

<dependency> 
    <groupId>com.microsoft.sqlserver</groupId> 
    <artifactId>mssql-jdbc</artifactId> 
    <version>6.2.1.jre8</version> 
</dependency> 

Come è sottolineato, se si utilizza una versione precedente, è possibile affrontare questo problema, e non è facile per eseguire il debug .

+0

Come un piccolo punto di fatto (numero di versione del driver) che migliora una risposta preesistente, sembra che questo dovrebbe essere stato inviato come commento o come una modifica ad altra risposta. –

Problemi correlati