在JDBC中处理Oracle“使用本地TimeZone的时间戳”数据类型

时间:2014-12-08 16:25:55

标签: java jdbc oracle11g timestamp sqldatatypes

我正在尝试使用JDBC调用PL / SQL过程(使用下面提到的签名)。它采用TIMESTAMP WITH LOCAL TIME ZONE类型的参数。我使用的是Oracle 11gOracle 12c Jdbc Driver Version 12.1.0.2

-- PURPOSE: Takes a timestamp and returns the formatted string
PROCEDURE deal_With_TimeStamp(intime TIMESTAMP WITH LOCAL TIME ZONE , outTimeString OUT VARCHAR2) 

我编写了一个使用JDBC调用上述过程的Java方法。我最终希望在Web服务中公开此方法。

我试图了解在这种情况下如何处理TIMESTAMP WITH LOCAL TIME ZONE类型的参数。

根据我的阅读,似乎TIMESTAMP WITH LOCAL TIME ZONE将根据数据库实例运行的时区对所有时间戳进行规范化。一旦将其考虑在内,它将丢弃客户端时区信息(如果提供)用于规范化过程。因此,如果客户端请求此信息,他们将不得不再次传递他们的时区信息以及请求。

在这种情况下,我是否应该接受来自Web服务客户端的时间戳和时区?这样,存储在数据库中的信息将是准确的。

没有时区信息发送时会发生什么?有没有办法为Jdbc连接设置时区?如果没有客户端的时区信息,可以将其传递给数据库。

以下是我使用JDBC的Java方法的相关部分。

 public void dealWithTimeStamp(Timestamp currentTimestampValue , String clientTimeZone)
 {
     Connection conn = null;
     CallableStatement callStmt = null;

     // Create a Database connection
     conn = DriverManager.getConnection(DB_URL , DB_USER , DB_PWD);

     // Create a query string
     String callProc = "{call HR.EMP_PKG.deal_With_TimeStamp ( ? , ?) }";

     // Create a Callable statement
     callStmt = conn.prepareCall(callProc);

     // Bind values to the IN parameter
     callStmt.setTimestamp(1, currentTimestampValue , Calendar.getInstance(TimeZone.getTimeZone(clientTimeZone)));

     // Register OUT parameters
     callStmt.registerOutParameter(2, java.sql.Types.VARCHAR);

     // Execute the Callable Statement
     callStmt.execute();

     // Retrieve the values from the OUT parameter
     String curTimestampStr = callStmt.getString(2);
     System.out.println("Current Timestamp : " + curTimestampStr);   
 }

请注意我已经对try catch块进行了条带化​​,为了便于阅读而清理了数据库资源

1 个答案:

答案 0 :(得分:1)

  

根据我的阅读,似乎TIMESTAMP WITH LOCAL TIME ZONE将根据数据库实例运行的时区对所有时间戳进行规范化。一旦规范化完成,它将丢弃客户端时区信息(提供时)。

是,the docs指定此数据类型仅包含时间戳本身,而不包含时区字段。它与TIMESTAMP的不同之处在于,传入值从客户端会话时区转换为数据库时区,传出值从另一个方向转换。

  

因此,如果客户请求此信息,他们将不得不再次传递他们的时区信息。

这取决于你所说的“客户”。 Web服务主机是数据库的客户端。它的时区是数据库会话的属性,因此您根本不必显式“传递”它。

但是,如果您指的是Web服务客户端,并且如果Web服务客户端需要提交和接收相对于其本地时区的时间戳(必须将其解释为此类型),则Web服务必须在其客户端之间转换时间戳。区域及其自己的区域,其中相应的Oracle数据类型为TIMESTAMP WITH LOCAL TIME ZONE。为此,Web服务客户端必须为Web服务提供时区。

根据Web服务客户端的特性修改数据库连接的会话属性我会感到很不舒服。这似乎容易出错。如果您必须处理时区问题,那么我建议您通过标准化时区来解决问题:

  • 让Web服务客户端接口指定以UTC格式给出和返回时间戳。然后,Web服务只需担心在一对时区之间进行转换。它可以通过将会话时区设置为UTC(通过ALTER SESSION语句),每个连接一次,或者可以用Java进行半自动来实现。
  • (可选)将数据库更改为使用普通TIMESTAMP,这应理解为以UTC表示。那么你根本不需要担心时区(与之前的结合)。

JDBC中没有标准的连接时区,但连接确实具有通用的“客户端属性”。 Oracle驱动程序可能会将会话时区公开为此类属性,在这种情况下,您可以通过Connection.setClientProperties()进行设置。同样,我个人会基于Web服务客户端数据避免这样做,但我可以基于Web服务主机做这件事。