2012-08-17 9 views
11

Ho cercato in giro, e sorprendentemente non riesco a trovare una risposta a questo per Oracle JDBC. This closely related question ha risposte per PostgreSQL e MySQL.Nel driver JDBC Oracle, cosa succede al fuso orario quando si scrive una data Java su una colonna TIMESTAMP?

In sostanza, se si dispone di due server applicazioni in due fusi orari diversi che scrivono timestamp su un database Oracle, cosa succederà? Grazie.

Modifica: devo aggiungere che sembra che il valore che JDBC sta inviando al database quando eseguo le interrogazioni è nel fuso orario locale.

+0

Perché si sta facendo questo nel front-end quando il database potrebbe farlo centralmente? – Tim

+0

Sto cercando di capire cosa fa il driver JDBC. Sembra che, nei miei registri, stia inviando una stringa che rappresenta l'ora locale di Oracle. Questo mi infastidisce. – drinian

+0

[questo documento] (http://docs.oracle.com/javase/1.3/docs/guide/jdbc/spec2/jdbc2.1.frame10.html) suggerisce che ciò che viene inviato dal driver JDBC non è un normalizzato (cioè UTC) timestamp ma un timestamp locale fuso orario (che chiamerei casuale) e il server dovrebbe calcolare la sua data utilizzando il fuso orario del server che ha il driver. Questo è in accordo con la tua scoperta. E sì, questo è preoccupante. –

risposta

8

Ho messo insieme un codice JDBC di prova per capire esattamente cosa succede. I risultati sono stati interessanti. Oracle ha tre tipi di dati strettamente correlati: TIMESTAMP, TIMESTAMP WITH TIME ZONE e TIMESTAMP WITH LOCAL TIME ZONE. Ho preso lo stesso identico codice e l'ho eseguito da due diversi box, uno nel fuso orario "America/New_York" e uno in esecuzione su UTC. Entrambe colpiscono lo stesso database, in esecuzione in UTC. Stavo usando il driver Oracle 11.2.0.2.0.

  • La colonna TIMESTAMP è stata impostata su qualunque fosse l'ora locale sulla macchina che esegue il codice Java. Non è stata eseguita la traduzione del fuso orario.
  • La colonna TIMESTAMP WITH TIME ZONE tradotto il tempo a qualsiasi fuso orario del client JDBC era in.
  • La colonna TIMESTAMP WITH LOCAL TIME ZONE anche tradotto il tempo a qualsiasi fuso orario del client JDBC era in.

This article, che è un po 'più vecchio , indica che TIMESTAMP WITH TIME ZONE è praticamente inutile se si desidera fare qualcosa come indici o partizioni. Tuttavia, sembra che TIMESTAMP WITH LOCAL TIME ZONE potrebbe essere estremamente utile. (Non sei sicuro di cosa succede se cambi il fuso orario del server, ma sembra intelligente sui fusi orari locali dei client JDBC). Non ho avuto la possibilità di testare il comportamento dell'indicizzazione, ecc. Con questi tipi di dati.

Incollare nella seguente classe di esempio se si desidera riprodurre i test nel proprio ambiente.

import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.Timestamp; 
import java.util.Date; 

// create table x_tst_ts_tab(
// os_name varchar(256) 
// ts timestamp, 
// ts_with_tz timestamp with time zone, 
// ts_with_local_tz timestamp with local time zone 
//) 
class TSTest { 
    public static final void main(String[] argv) throws Exception { 
     Class.forName("oracle.jdbc.OracleDriver"); 
     Connection conn = DriverManager.getConnection(
      "your_connection_string", 
      "your_user_name", 
      "your_password"); 

     try { 
      // Insert some data 
      Date nowDate = new Date(); 
      Timestamp nowTimestamp = new Timestamp(nowDate.getTime()); 
      PreparedStatement insertStmt = conn.prepareStatement(
       "INSERT INTO x_tst_ts_tab" 
       + " (os_name, ts, ts_with_tz, ts_with_local_tz)" 
       + " VALUES (?, ?, ?, ?)"); 
      try { 
       insertStmt.setString(1, System.getProperty("os.name")); 
       insertStmt.setTimestamp(2, nowTimestamp); 
       insertStmt.setTimestamp(3, nowTimestamp); 
       insertStmt.setTimestamp(4, nowTimestamp); 
       insertStmt.executeUpdate(); 
      } finally { 
       try { 
        insertStmt.close(); 
       } catch (Throwable t) { 
        // do nothing 
       } 
      } 

      System.out.println("os_name, ts, ts_with_tz, ts_with_local_tz"); 

      // Read back everything in the DB 
      PreparedStatement selectStmt = conn.prepareStatement(
       "SELECT os_name, ts, ts_with_tz, ts_with_local_tz" 
       + " FROM dom_fraud_beacon.x_tst_ts_tab"); 
      ResultSet result = null; 
      try { 
       result = selectStmt.executeQuery(); 
       while (result.next()) { 
        System.out.println(
         String.format("%s,%s,%s,%s", 
             result.getString(1), 
             result.getTimestamp(2).toString(), 
             result.getTimestamp(3).toString(), 
             result.getTimestamp(4).toString() 
            )); 
       } 
      } finally { 
       try { 
        result.close(); 
       } catch (Throwable t) { 
        // do nothing 
       } finally { 
        try { 
         selectStmt.close(); 
        } catch (Throwable t) { 
         // do nothing 
        } 
       } 
      } 
     } finally { 
      try { 
       conn.close(); 
      } catch (Throwable t) { 
       // do nothing 
      } 
     } 
    } 
} 
+0

Vedere anche http://stackoverflow.com/questions/2858182/preparedstatement-and-settimestamp-in-oracle-jdbc – drinian

+2

Qual è il risultato di 'System.out.println'? –

Problemi correlati