2012-08-17 25 views
11

Tôi đã tìm kiếm xung quanh, và đáng ngạc nhiên không thể tìm thấy câu trả lời cho điều này cho Oracle JDBC. This closely related question có câu trả lời cho PostgreSQL và MySQL.Trong trình điều khiển JDBC Oracle, điều gì sẽ xảy ra với múi giờ khi bạn viết một ngày Java vào cột TIMESTAMP?

Về cơ bản, nếu tôi có hai máy chủ ứng dụng trong hai múi giờ khác nhau viết dấu thời gian cho một cơ sở dữ liệu Oracle, điều gì sẽ xảy ra? Cảm ơn.

Chỉnh sửa: Tôi nên thêm rằng nó có vẻ giống như giá trị mà JDBC gửi đến cơ sở dữ liệu khi tôi thực hiện truy vấn trong múi giờ địa phương của tôi.

+0

Tại sao bạn làm điều đó trong giao diện người dùng khi cơ sở dữ liệu có thể thực hiện điều đó một cách tập trung? – Tim

+0

Tôi đang cố gắng hiểu những gì trình điều khiển JDBC làm. Có vẻ như, trong nhật ký của tôi, nó gửi một chuỗi biểu diễn thời gian cục bộ cho Oracle. Điều này làm phiền tôi. – drinian

+0

[tài liệu này] (http://docs.oracle.com/javase/1.3/docs/guide/jdbc/spec2/jdbc2.1.frame10.html) gợi ý rằng những gì được gửi bởi trình điều khiển JDBC không phải là một chuẩn hóa (tức là UTC) dấu thời gian nhưng một dấu thời gian địa phương múi giờ (những gì tôi sẽ gọi ngẫu nhiên) và máy chủ có nghĩa vụ phải tính toán ngày của nó bằng cách sử dụng múi giờ của máy chủ có trình điều khiển. Điều này phù hợp với phát hiện của bạn. Và có điều này là làm phiền. –

Trả lời

8

Tôi tập hợp một số mã JDBC thử nghiệm để tìm ra chính xác những gì sẽ xảy ra. Kết quả thật thú vị. Oracle có ba kiểu dữ liệu có liên quan chặt chẽ: TIMESTAMP, TIMESTAMP WITH TIME ZONETIMESTAMP WITH LOCAL TIME ZONE. Tôi lấy chính xác mã đó và chạy nó từ hai hộp khác nhau, một trong múi giờ "America/New_York" và một chạy trên UTC. Cả hai đều nhấn cùng một cơ sở dữ liệu, chạy trong UTC. Tôi đã sử dụng trình điều khiển Oracle 11.2.0.2.0.

  • Cột TIMESTAMP được đặt thành bất kỳ thời gian cục bộ nào trên máy thực thi mã Java. Không có bản dịch múi giờ nào được thực hiện.
  • Cột TIMESTAMP WITH TIME ZONE dịch thời gian để bất cứ điều gì múi giờ client JDBC là trong.
  • Cột TIMESTAMP WITH LOCAL TIME ZONE cũng dịch thời gian để bất cứ điều gì múi giờ client JDBC là trong.

This article, đó là một chút cũ , chỉ ra rằng TIMESTAMP WITH TIME ZONE là khá nhiều vô ích nếu bạn muốn làm bất cứ điều gì giống như chỉ mục hoặc phân vùng. Tuy nhiên, có vẻ như TIMESTAMP WITH LOCAL TIME ZONE có thể cực kỳ hữu ích. (Bạn không chắc chắn điều gì sẽ xảy ra nếu bạn thay đổi múi giờ của máy chủ, nhưng có vẻ thông minh về múi giờ địa phương của khách hàng JDBC). Tôi đã không có cơ hội để kiểm tra hành vi lập chỉ mục, v.v. với các kiểu dữ liệu này.

Dán trong lớp mẫu của tôi dưới đây nếu bạn muốn tái tạo các thử nghiệm của mình trong môi trường của bạn.

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

Xem thêm http://stackoverflow.com/questions/2858182/preparedstatement-and-settimestamp-in-oracle-jdbc – drinian

+2

Kết quả của 'System.out.println' là gì? –

Các vấn đề liên quan