我有一些日期存储在Oracle中,Oracle的TIMESTAMP(3)
作为其数据类型。现在我正在编写一个Spring启动应用程序来读取这些值。代码如下:
HibernateCallback callback = new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
Query query = session.createSQLQuery("SELECT date_field FROM some_table WHERE some_conditions");
return query.list();
}
};
所以:
List results = (List)getHibernateTemplate().execute(callback);
// suppose there's only one row and one column returned
Timestamp ts = result.get(0)[0];
返回由Hibernate自动创建的Java Timestamp
对象。问题是,在构造对象时,它会忽略存储在Oracle中的时区,而是使用JVM的默认时区。我测试的是为JVM设置不同的时区,每次生成不同的时间戳。
这显然是错的。日期在时间线上应该是唯一的。它不应该依赖于JVM的时区。我想知道在解析日期时包含DB的时区信息的正确方法是什么。现在看起来它只是使用存储在Oracle中的String表示并用JMV的时区解析它。我正在使用Hibernate 4.3.4.Final
。
PS:实际查询是高度自定义的,所以我必须编写原始SQL。
答案 0 :(得分:4)
基本上,这甚至不是Hibernate的问题,而是JDBC的问题。默认情况下,JDBC驱动程序将使用运行JVM的系统时区。如果要连接到不同时区的数据库服务器,或者即使您希望独立于系统的当前时区,最好明确设置JDBC时区。
您可以使用Offset(0,1)
属性来设置时区,也可以在运行时通过。
hibernate.jdbc.time_zone
对于Oracle,我会说你可以使用session = sessionFactory.withOptions()
.jdbcTimeZone(TimeZone.getTimeZone("UTC"))
.openSession();
来尊重你的JDBC客户端时区。
答案 1 :(得分:0)
问题在于您正在使用的Oracle列数据类型,如果您访问官方oracle文档link,您会注意到 TIMESTAMP 不尊重时区,因此您应该与Dictionary<string,IEnumerable<Rate>> groupedSet = new Dictionary<string, IEnumerable<Rate>>();
foreach (var key in currencyCode)
{
IEnumerable<Rate> _result = rate.Where(x => x.CurrencyCode.Contains(key));
if (_result.Any())
{
groupedSet.Add(key, _result);
}
}
或TIMESTAMP WITH TIME ZONE
一起使用。
答案 2 :(得分:0)
似乎问题在于日期处理的概念很少
如果您在数据库中根据UTC获取日期,然后检查hibernate查询的输出,您应该看到日期根据JVM的时区进行了更改。
如果您想要返回相同的日期(如在DB中),也许您应该将日期转换为UTC时区。
现在,您可以执行以下任一操作: