Prima di scrivere una data Java su una colonna SQL TIMESTAMP, JDBC traduce la data dal fuso orario della JVM al fuso orario della sessione del database?

Prima di scrivere una data Java su una colonna SQL TIMESTAMP , JDBC traduce la data dal fuso orario della macchina virtuale Java a quella della sessione del database?

Ad esempio, si supponga che il fuso orario della macchina virtuale Java sia UTC e che il fuso orario della sessione del database sia UTC-5 . Se un programma Java tenta di memorizzare 2000-01-01 00:00:00 passandolo a PreparedStatement#setTimestamp(int, Timestamp) , secondo lo standard JDBC, lo store di database TIMESTAMP '2000-01-01 00:00:00' o TIMESTAMP '1999-12-31 19:00:00' ?

No, JDBC è solo un’API su come il client può accedere al database. Per la memorizzazione di timestamp, questo dovrà dipendere dall’organizzazione che scrive i driver di database conformi allo standard dell’API JDBC.

Ecco un’implementazione dell’implementazione di MySQL di PreparedStatement . Sembrano prendere il fuso orario JVM di Java in MySQL Timezone (controlla il metodo setTimestampInternal() ).

Ora il mio requisito è che dovrebbe memorizzare il valore in GMT / UTC indipendentemente dal fuso orario della JVM. C’è un modo per impostare il fuso orario al volo e quindi per annullarlo una volta che ho finito con JDBC?

Modifica: Ok, ho trovato un modo per aggirare quel problema. Ha fatto quanto segue

 TimeZone default = TimeZone.getDefault(); try { TimeZone.setDefault(TimeZone.getTimeZone("UTC")); //Do stuff with JDBC } finally { TimeZone.setDefault(default); } 

Puoi utilizzare il settaggio setTimestamp sovraccarico che accetta l’istanza di Calendar per specificare il fuso orario

Esempio (se stai usando Joda datetime):

 org.joda.time.DateTime sendDateUTC = new DateTime( DateTimeZone.UTC ).withMillis( millis ); statement.setTimestamp (1, sendDateUTC, sendDateUTC.toGregorianCalendar() ); 

Come per javaDoc: imposta il parametro designato sul valore java.sql.Timestamp specificato, utilizzando l’object Calendar specificato. Il driver utilizza l’object Calendar per build un valore SQL TIMESTAMP , che il driver quindi invia al database. Con un object Calendar , il conducente può calcolare il timestamp tenendo conto di un fuso orario personalizzato. Se non viene specificato alcun object Calendar, il driver utilizza il fuso orario predefinito, che è quello della macchina virtuale che esegue l’applicazione.

 void setTimestamp(int parameterIndex, java.sql.Timestamp x, Calendar cal) throws SQLException; 

Le specifiche sono stupide. Java.util.Date memorizza millisecondi di epoca nel frame di riferimento GMT. Java.sql.Timestamp è una data più nanosecondi nello stesso fotogramma di riferimento. Tutti i getter e setter non deprecati usano il frame di riferimento GMT. Per qualsiasi tipo di sanità mentale, il fuso orario predefinito per la memorizzazione di un Timestamp dovrebbe essere GMT.

In un’applicazione a più livelli, il front-end, il driver e il server del database potrebbero essere tutti in fusi orari diversi. Alcuni dei livelli potrebbero essere in fusi orari diversi contemporaneamente; ad esempio, se stai eseguendo il bilanciamento del carico su Internet in un continente o se hai un’app mobile che si connette a un server centrale. Un ambiente operativo cloud sarebbe lo stesso scenario in cui non si ha idea di dove verrà eseguito il driver JDBC, né alcuna garanzia che non cambierà mai.

L’unico modo che conosco per raggiungere la coerenza in questi ambienti è utilizzare solo il set di parametri e il getter ResultSet che accettano un calendario e assicurarsi che ogni app che accede ai dati utilizzi un calendario, preferibilmente GMT o UTC.