Oracle 正确使用org.joda.time.contrib.hibernate.PersistentDateTime,并将webapp配置为与db不同的时区

Oracle 正确使用org.joda.time.contrib.hibernate.PersistentDateTime,并将webapp配置为与db不同的时区,oracle,hibernate,spring,timezone,jodatime,Oracle,Hibernate,Spring,Timezone,Jodatime,我相信这已经被多次遇到,并且在其他地方被写过。对于这篇冗长的文章,我提前表示歉意,但我想在前面提供尽可能多的细节 我有一个在一个时区运行JVM的工作站(在我的例子中是-07:00)。我有一个Oracle数据库,配置为以UTC保存日期值 我正在尝试使用jodatime扩展,它具有自定义的Hibernate类型,其中之一是PersistentDateTime 下面是my.hbm.xml中的一个示例 <hibernate-mapping> <class name="com.spp.m

我相信这已经被多次遇到,并且在其他地方被写过。对于这篇冗长的文章,我提前表示歉意,但我想在前面提供尽可能多的细节

我有一个在一个时区运行JVM的工作站(在我的例子中是-07:00)。我有一个Oracle数据库,配置为以UTC保存日期值

我正在尝试使用jodatime扩展,它具有自定义的Hibernate类型,其中之一是PersistentDateTime

下面是my.hbm.xml中的一个示例

<hibernate-mapping>
<class name="com.spp.mui.domain.MktBidHourly" table="MKTBIDHOURLY">
    <comment>Entity to represent the hourly participant bids</comment>
    <id name="bidId" type="big_decimal">
        <column name="BIDID" precision="22" scale="0" />
        <generator class="foreign">
            <param name="property">mktBid</param>
        </generator>
    </id>
    <one-to-one name="mktBid" class="com.spp.mui.domain.MktAbstractBid" constrained="true"></one-to-one>

    <property name="period" type="org.joda.time.contrib.hibernate.PersistentDateTime">
        <column name="PERIOD" length="7">
            <comment>Identifies the Period for which the bid applies.</comment>
        </column>
    </property>
    <property name="bidCurveId" type="big_decimal">
        <column name="BIDCURVEID" precision="22" scale="0">
            <comment>A database-generated unique identifier for the bid curve</comment>
        </column>
    </property>
</class>
这是测试方法

@Test
public void testFindVirtualBids() throws ParseException {
    List<MktVirtualBid> candidateBids = new ArrayList<MktVirtualBid>();
    MktBidType bidType = new MktBidType(MktBid.VIRTUAL_BID);
    candidateBids.add(data.createMktVirtualBid(new BigDecimal(LOCATION_ID_1), false, timeDispatcher.getDateTimeFromXMLDateTime("2011-08-03T13:00:00-07:00"), new BigDecimal(CURVE_ID_1)));
    candidateBids.add(data.createMktVirtualBid(new BigDecimal(LOCATION_ID_2), false, timeDispatcher.getDateTimeFromXMLDateTime("2011-08-04T13:00:00-07:00"), new BigDecimal(CURVE_ID_2)));
    List<MktVirtualBid> foundBids = dao.findVirtualBids(bidType, new BigDecimal(PARTICIPANT_ID), candidateBids);
    Assert.assertEquals(2, foundBids.size());
}
作为格式化程序,然后

parseDateTime(xmlDateTime).withZone(DateTimeZone.UTC)
获取日期时间

下面是测试运行的一些示例输出(很抱歉格式设置不好)

16:22:31729调试[AbstractBatcher]即将打开PreparedStatement(打开PreparedStatements:0,全局:0)
16:22:31732调试[SQL]
选择
mktbid0。BIDID作为BIDID5,
mktbid0。BIDTYPE作为BIDTYPE5,
mktbid0_u0.PARTICIPANTID作为PARTICIP3_5,
mktbid0_u0.PNODEID作为PNODEID5_0,
mktbid0_u0.usebidslop作为USEBIDSL5_5_0

DEVMOI2.MKTBID mktbid0_2;,
DEVMOI2.MKTBIDHOURLY mktbidhour1\ubr> 其中
mktbid0_u0.BIDID=mktbidhour1_u0.BIDID
和(
mktbid0_u0.PNODEID in(
?,?
)
)
和(
mktbidhour1_uu1.时段单位(
?,?
)
)
和mktbid0.BIDTYPE=?
和mktbid0_u0.PARTICIPANTID=?休眠:
选择
mktbid0。BIDID作为BIDID5,
mktbid0。BIDTYPE作为BIDTYPE5,
mktbid0_u0.PARTICIPANTID作为PARTICIP3_5,
mktbid0_u0.PNODEID作为PNODEID5_0,
mktbid0_u0.usebidslop作为USEBIDSL5_5_0

DEVMOI2.MKTBID mktbid0_2;,
DEVMOI2.MKTBIDHOURLY mktbidhour1\ubr> 其中
mktbid0_u0.BIDID=mktbidhour1_u0.BIDID
和(
mktbid0_u0.PNODEID in(
?,?
)
)
和(
mktbidhour1_uu1.时段单位(
?,?
)
)
和mktbid0.BIDTYPE=?
和mktbid0_u0.PARTICIPANTID=?
16:22:31733跟踪[AbstractBatcher]准备语句
16:22:31798跟踪[BasicBinder]绑定参数[1]为[NUMERIC]-262235
16:22:31798跟踪[BasicBinder]绑定参数[2]为[NUMERIC]-262234
16:22:31799跟踪[BasicBinder]绑定参数[3]为[TIMESTAMP]-2011年8月3日星期三13:00:00 PDT
16:22:31799跟踪[BasicBinder]绑定参数[4]为[TIMESTAMP]-2011年8月4日星期四13:00:00 PDT
16:22:31801跟踪[BasicBinder]绑定参数[5]为[VARCHAR]-D
16:22:31801跟踪[BasicBinder]绑定参数[6]为[NUMERIC]-260699

然后测试失败了

结果:

失败的测试:
testFindVirtualBids(com.spp.mui.persistence.hibernate.MktBidDAOTest):应为:但为:

测试运行:2,失败:1,错误:0,跳过:0


为什么我的测试断言不能通过

我自己解决了这个问题。我如何插入日期的棘手部分。我选择了另一条路线,不幸的是,我无法共享该路线的代码。我开发了一个测试基类,其中包含一个用于加载CSV文件的例程。它利用了Spring的TestContext框架,特别是@BeforeTransation注释方法,该方法委托助手处理各种字符串类型(例如,日期、数字、字节[]等)

格式化程序基本上是正确的。对于那些好奇的人来说,timeDispatcher的方法impl看起来像这样

 public DateTime getDateTimeFromXMLDateTime(String xmlDateTime) {  
    if(xmlDateTime == null || "".equals(xmlDateTime)) {  
        return null;  
    } else {  
        return isoParser.parseDateTime(xmlDateTime).withZone(gmtTZ);  
    }  
}  
在哪里

isoParser = ISODateTimeFormat.dateTimeParser(DateTimeZone.getDefault());  


我应该补充一点,当我尝试运行Hibernate发出的查询时,在Toad之类的工具中替换param值,我会得到结果。
 public DateTime getDateTimeFromXMLDateTime(String xmlDateTime) {  
    if(xmlDateTime == null || "".equals(xmlDateTime)) {  
        return null;  
    } else {  
        return isoParser.parseDateTime(xmlDateTime).withZone(gmtTZ);  
    }  
}  
isoParser = ISODateTimeFormat.dateTimeParser(DateTimeZone.getDefault());  
gmtTZ = DateTimeZone.UTC;