Oracle 12的@Temporal(TemporalType.DATE)

在我们的DB中,我们有多个具有Date字段的实体。 Oracle将每个日期视为相同,具有日期和时间部分。 然而,JPA实体通过annotaton @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之间切换时,此代码段的行为会有所不同。

我们已经联合了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参数中