java - 在 JDBC 中处理 Oracle 的 "Timestamp With local TimeZone"数据类型

标签 java jdbc oracle11g timestamp sqldatatypes

我正在尝试使用 JDBC 调用 PL/SQL 过程(具有下面提到的签名)。它采用TIMESTAMP WITH LOCAL TIME ZONE类型的参数。我正在使用 Oracle 11gOracle 12c Jdbc 驱动程序版本 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) 

我编写了一个 Java 方法 a,它使用 JDBC 调用上述过程。我最终想在网络服务中公开这个方法。

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

据我所知,TIMESTAMP WITH LOCAL TIME ZONE 将根据数据库实例运行的时区对所有时间戳进行标准化。它将丢弃客户端时区信息(如果提供) ,一旦考虑到标准化过程。因此,如果客户端请求此信息,他们将必须随请求再次传递时区信息。

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

如果没有发送时区信息会发生什么?有没有办法为 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 block 进行了 strip 化​​,清理了数据库资源:

最佳答案

From what I have read it seems like TIMESTAMP WITH LOCAL TIME ZONE will have all Timestamps normalized based on the timezone in which the database instance operates.It will discard the client timezone information (when supplied) , once the normalization is done.

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

So if the client requests for this info they will have to pass their timezone info again along with the request.

这取决于您指的是哪个“客户”。 Web 服务主机是数据库的客户端。它的时区是数据库 session 的一个属性,因此您根本不必显式“传递”它。

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

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

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

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

关于java - 在 JDBC 中处理 Oracle 的 "Timestamp With local TimeZone"数据类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27362348/

相关文章:

java - JTextField 的 "column"的宽度是多少?

java - 从 IntelliJ IDEA (Android) 运行 JUnit 测试时为 "Class not found"

java - 转换为 byte[] 和 String.getBytes

java - hive 和 spark 分布的 hive thrift 服务器之间的区别

java - 了解神秘的 Oracle JDBC 错误 - ORA-00911 : invalid character

sql - 如何在oracle中获取最近两年的年度数据

oracle11g - 如何使 CLOBAGG 函数对结果进行排序?

java - 如何检查哪个子类被传递到构造函数中?

java - JDBC 类路径问题

sql - 如何编写 SQL 查询以在 Oracle 中查找最高和最低工资以及员工姓名