38

当您将日期分配给命名 SQL 参数时,Hibernate 会自动将其转换为 GMT 时间。你如何让它在所有日期都使用当前服务器时区?

假设您有一个查询:

Query q = session.createQuery("from Table where date_field < :now");
q.setDate("now", new java.util.Date());

“now” 将设置为 GMT 时间,而“new Date()” 获取您当前的服务器时间。

谢谢。

4

5 回答 5

68

事实证明,Hibernate 不会自动将日期转换为 GMT,如果你使用它只会切断时间query.setDate(),所以如果你通过 "2009-01-16 12:13:14" 它变成 "2009-01-16 00:00 :00”。

要考虑时间,您需要query.setTimestamp("date", dateObj)改用。

于 2009-01-16T21:45:10.867 回答
2

Hibernate 不知道时区。任何时区转换都应在执行查询之前完成。

例如,如果您的数据库服务器设置为 CST,但用户使用的是 EST,则您需要将 1 小时添加到作为查询输入的任何时间戳。

于 2008-11-14T22:27:18.497 回答
2

我们使用自定义的 Hibernate 日期类型。每当我们在查询上设置参数时,我们都会使用基类或实用程序方法,这样我们就可以将用户的时区传递给自定义类型参数。

您可以通过手动调整实用程序方法中的时间来进行查询,但是这样读取或写入数据库的日期也可以正确转换。此方法还处理数据库将日期存储在其本地时区的情况。因此,即使您在一个时区有一个用户,在另一个时区有一个数据库服务器,并且 Java 使用 GMT,它也可以让一切变得简单。它最终看起来像:

Properties properties = new Properties();
properties.setProperty("timeZone", databaseTimeZone);
query.setParameter("from", dateEnteredByUser, Hibernate.custom(LocalizedDateType.class, properties));

作为额外的奖励,我们使用它来处理 SQL Server 将 23:59:59.999 转换为第二天的事实。在自定义类型中,我们检查并取消它。

于 2008-11-15T01:42:04.533 回答
2

如果您需要时区同步值,您可以在 HQL 中使用now()。另外我建议您使用 Joda 库。它有一个休眠插件模块。

于 2011-11-17T10:11:25.057 回答
1

自5.2版以来, Hibernate 团队已弃用setTimestamp(String name, Date val)方法以及org.hibernate.Query接口:

 /* @deprecated (since 5.2) use {@link #setParameter(int, Object)} or
    {@link #setParameter(int, Object, Type)}  instead
 */

所以你可以使用下面的代码:

import org.hibernate.query.Query;
...
Query query = session.createQuery("from Table where date_field < :now");
query.setParameter("now", new Date(), TimestampType.INSTANCE );

值得注意的是,减少时间部分的setDate方法也被弃用,可以用这个选项替换(来自相同的接口 org.hibernate.query.Query):

query.setParameter("firstMomentOfToday", new Date(), DateType.INSTANCE);

If you are going to use it with java 8 and the relevent jdbc drivers like Oracle 'ojdbc8.jar' and supported hibernate versions this might not work as expected, so it's wise to use new java.time.LocalDate and LocalDateTime instead.

于 2018-07-17T06:36:32.583 回答