【问题标题】:@Temporal(TemporalType.DATE) with Oracle 12@Temporal(TemporalType.DATE) 与 Oracle 12
【发布时间】:2016-01-18 20:28:54
【问题描述】:

在我们的数据库中,我们有多个带有日期字段的实体。 Oracle 将每个日期视为相同的日期和时间部分。然而,JPA 实体通过注释 @Temporal 进行区分。当我们想省略时间部分时,我们用@Temporal(TemporalType.DATE) 注释日期字段,Oracle 保存 00:00:00,如果没有,我们就不用注释了。

例子:

@Entity
public class MyEntity implements Serializable {
  private static final long serialVersionUID = 1L;

  @Id
  private long myentityId;

  @Temporal(TemporalType.DATE)
  private Date importantDate; //01.01.2015 00:00:00

  private Date creationDate; //01.01.2015 10:35:51
  ...
}

...
MyEntity me = new MyEntity();
me.setImportantDate(new Date());
me.setCreationDate(new Date());
...

我们从 Oracle 11 升级到 Oracle 12,现在 importantDate 的时间部分不再省略!

我使用完全相同的程序在两个数据库上对此进行了广泛的测试。 这实际上破坏了我们的应用程序。

我可以做些什么来恢复以前的行为?


更新 1: 我缩小了问题范围:驱动程序 ojdbc6 12.1.0.1.0 有问题,ojdbc6 11.2.0.3.0 按预期工作。 (都使用 Oracle 12 DB)

这是 11.1 中修复的时间戳问题的延续吗? (http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-faq-090281.html#08_01)


更新 2: 由于Hibernate似乎不是问题,我用纯JDBC写了一个例子:

OracleDataSource ods = new OracleDataSource();
...
Connection conn = ods.getConnection();
PreparedStatement ps = conn.prepareStatement("UPDATE MyEntity SET importantDate = ? WHERE myentityId = 4385");
ps.setDate(1, new java.sql.Date(new java.util.Date().getTime()));
ps.execute();
...

在 ojdbc6 11.1 和 ojdbc6 12.1 之间切换时,此 sn-p 的行为有所不同。

【问题讨论】:

  • 您是否也更新了应用程序中的 Oracle 驱动程序?
  • 您使用的是哪个版本的 Hibernate?你在用Oracle12cDialect吗?
  • 我们仍然使用 org.hibernate.dialect.Oracle10gDialect 和 OJDBC7 驱动。现在将尝试新的方言。
  • 确实有人想知道为什么 Hibernate 不能自动检测正在使用的 RDBMS 并选择正确的“方言”。毕竟,其他 JPA 提供者可以做到这一点
  • @Thomas6767:我们尝试安装一些 Oracle WL 补丁。也没有用。这里解释了一个解决方法:stackoverflow.com/questions/10429276/…。虽然这不是一个非常令人满意的解决方案。您是否考虑过 Oracle 服务请求?

标签: java oracle hibernate jpa oracle12c


【解决方案1】:

我们已联系 Oracle 支持,他们回复如下(很遗憾,我无法提供答案链接,因为需要 Oracle 支持帐户):

新行为按预期工作

在 JDBC 12.1.0.1 中,getDate 和 setDate 不会截断日期的时间部分。此行为与 JDBC 11.2.0.X 不同,其中时间组件被截断。根据错误 14389749、17228297,此更改是故意的,并且 12c 驱动程序的行为是正确的。

提供的解决方法对我有用:

解决方法 #1: 修改应用程序以不插入时间组件(例如使用静态 UtilMethod)

public static Date truncateTime(Date date) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); return calendar.getTime(); }

解决方法 #2: 从 MOS 下载并应用补丁 19297927:(My Oracle Support)

  1. 点击补丁和更新选项卡。
  2. 输入上面的补丁号并点击搜索。
  3. 从列表中点击你平台对应的补丁号
  4. 点击下载按钮下载补丁。
  5. 下载前请阅读所有适用说明,然后单击“下载”按钮。

修补后替换 %Oracle_Home%\oracle_common\modules\oracle.jdbc_12.1.0 中的 ojdb7.jar 并将 -Doracle.jdbc.DateZeroTime=true 添加到您的 JVM 参数中

【讨论】:

  • 感谢您提供详细信息。当 Oracle 支持人员告诉我们该行为符合预期且 Apache 的 Hibernate 团队没有响应时,我们实施了带有触发器的解决方法,以便将来保存。
猜你喜欢
  • 2011-06-23
  • 1970-01-01
  • 1970-01-01
  • 2011-07-15
  • 1970-01-01
  • 2020-05-13
  • 2016-09-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多