【问题标题】:Hibernate and oracle issues with timestamps and daylight saving时间戳和夏令时的休眠和 Oracle 问题
【发布时间】:2012-10-22 20:53:11
【问题描述】:

我正在尝试使用定义将数据添加到 oracle 11g 数据库中的表中。

CREATE TABLE FOO_TIME_TEST  
(ID      NUMBER(20) NOT NULL, TIME    TIMESTAMP(6),
 CONSTRAINT FOO_TIME_TEST_PK   PRIMARY KEY (ID) USING INDEX);

CREATE UNIQUE INDEX "foo_time_test_idx" ON "FOO_TIME_TEST" (TIME)

使用Joda时间的Hibernate/JPA映射如下

@Type(type = "com.foo.PersistentDateTime")
@Column(name = "TIME")
public DateTime getTime() {
    return time;
}

映射类PersistentDateTime相关位

public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index) throws SQLException {
    if (value == null) {
        Hibernate.TIMESTAMP.nullSafeSet(preparedStatement, null, index);
    } else {
        Hibernate.TIMESTAMP.nullSafeSet(preparedStatement, ((DateTime) value).toDate(), index);
    }
}

public int[] sqlTypes() {
    return new int[] { Types.TIMESTAMP, };
}

而要编写的代码是这样的,它是在一个循环中使用 plusTime() 但我将它隔离到这两个调用中。

{
    DateTime time = new DateTime(2012, 10, 28, 0, 0, DateTimeZone.UTC);
    FooTest data = new FooTest();
    data.setTime(time);
    em.persist(data);
    System.out.println(time + " " + time.getMillis() / 1000 / 60 / 60);
}

{
    DateTime time = new DateTime(2012, 10, 28, 1, 0, DateTimeZone.UTC);
    FooTest data = new FooTest();
    data.setTime(time);
    em.persist(data);
    System.out.println(time + " " + time.getMillis() / 1000 / 60 / 60);
}

输出

2012-10-28T00:00:00.000Z 375384
2012-10-28T01:00:00.000Z 375385

19:23:42,081  WARN JDBCExceptionReporter:100 - SQL Error: 1, SQLState: 23000
19:23:42,081 ERROR JDBCExceptionReporter:101 - ORA-00001: unique constraint (Foo.foo_time_test_idx) violated

我已经尝试删除唯一索引,然后代码成功但数据库中的两行相同:

ID  Time
1   28-OCT-12 01.00.00.000000000 AM
2   28-OCT-12 01.00.00.000000000 AM

启用休眠跟踪后,似乎显示两个不同的日期被展平为相同的值。

Hibernate: insert into FOO_TIME_TEST (ID, TIME) values (?, ?)
07:38:54,217 TRACE TimestampType:151 - binding '2012-10-28 01:00:00' to parameter: 22
Hibernate: insert into FOO_TIME_TEST (ID, TIME) values (?, ?)
07:38:54,217 TRACE TimestampType:151 - binding '2012-10-28 01:00:00' to parameter: 22

确实需要 ojdbc-6.jar 的源来进一步调试...

我通过为 11.2.0.2.0 下载 ojdbc6_g.jar 并将类路径以及 -Doracle.jdbc.Trace=true 选项(如建议的 here 和自定义 java util log.properties)一起启用了更多调试

这会在每次绑定调用后提供附加信息,在这两种情况下都会显示 01:00 值。

Nov 2, 2012 8:20:21 AM oracle.jdbc.driver.OraclePreparedStatementWrapper setTimestamp
TRACE_30: 3C322E7D Enter: 22, 2012-10-28 01:00:00.0
Nov 2, 2012 8:20:21 AM oracle.jdbc.driver.OraclePreparedStatement setTimestamp
FINE: 3C322E7D Public Enter: 22, 2012-10-28 01:00:00.0
Nov 2, 2012 8:20:21 AM oracle.jdbc.driver.OraclePreparedStatement setTimestampInternal
FINER: 3C322E7D Enter: 22, 2012-10-28 01:00:00.0

【问题讨论】:

  • 如果它仍然是真实的:) 你能展示你的 FooTime 课程内容吗?也许你已经解决了这个问题?

标签: hibernate jpa timezone


【解决方案1】:

当您使用时区存储时间时,我建议使用类型 TIMESTAMP(3) WITH TIME ZONE。

CREATE TABLE TIME_TABLE
(
  YOUR_TIME TIMESTAMP(3) WITH TIME ZONE,
  TIME_ZONE  VARCHAR (64 BYTE),
)

对于休眠映射使用 Joda 类 org.joda.time.contrib.hibernate.PersistentDateTimeTZ,下面是 XML 映射 sn-p。

<property name="yourTime" type="org.joda.time.contrib.hibernate.PersistentDateTimeTZ">
    <column name="YOUR_TIME" />
    <column name="TIME_ZONE" />
</property>

我不熟悉基于注释的 Hibernate 映射,但我认为它看起来像(我还没有尝试过):

@Type(type = "org.joda.time.contrib.hibernate.PersistentDateTimeTZ")
@Columns(columns = { @Column(name = "YOUR_TIME"), @Column(name = "TIME_ZONE") })
public DateTime getYourTime() {
        return yourTime;
}

我希望这会有所帮助。

附:我不认识您正在使用的 Joda DateTime 构造函数:它似乎没有 Seconds 和 Milliseconds 参数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-15
    • 2011-12-22
    • 2011-10-22
    • 2012-03-25
    • 2015-07-31
    • 2014-08-22
    • 1970-01-01
    • 2015-12-18
    相关资源
    最近更新 更多