在我们的数据库中,我们有多个具有日期字段的实体。 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之间切换时,此代码段的行为有所不同。
答案 0 :(得分:2)
我们已经联合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 :(我的Oracle支持)
修补后替换%Oracle_Home%\oracle_common\modules\oracle.jdbc_12.1.0
中的ojdb7.jar并将-Doracle.jdbc.DateZeroTime=true
添加到JVM参数