3

我在使用 JPA 和 Oracle 并按小时分组时遇到问题。这是场景:我有一个名为 EventData 的条目。该实体有一个名为 startOfPeriod 的 java.util.Date 字段。此字段映射到数据类型 DATE 的表字段中。我正在使用的查询类似于:

select min(ed.startOfPeriod) as eventDate,
(...)
from
Event e inner join e.eventDatas ed
(...)
group by
    year(ed.startOfPeriod), 
    month(ed.startOfPeriod), 
    day(ed.startOfPeriod), 
    hour(ed.startOfPeriod) 
order by 1

如果我按“小时(ed.startOfPeriod)”删除该组,它工作正常(它不会产生任何错误,但它不会做我想要的)。当我插入这个 group by 子句时,它会出现这个异常:

Caused by: java.sql.SQLException: ORA-30076: campo de extração inválido para origem de extração
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288)
at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:745)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:219)
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:813)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1049)
at oracle.jdbc.driver.T4CPreparedStatement.executeMaybeDescribe(T4CPreparedStatement.java:854)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1154)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3370)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3415)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:92)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1812)
at org.hibernate.loader.Loader.doQuery(Loader.java:697)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
at org.hibernate.loader.Loader.doList(Loader.java:2232)

分析错误代码,当“提取源不包含指定的提取字段。”时发生。但是提取的来源(startOfPeriod 字段)是数据类型 DATE(它有一个小时部分)。

相同的代码在 SQL Server 中就像一个魅力。

有谁知道发生了什么?

天呐!

4

3 回答 3

2

您是否尝试过 TO_CHAR(d, 'HH24') ?你也可以 trunc() 到小时......

于 2010-10-01T13:02:09.207 回答
0

不完全是一个答案,但对我来说这听起来像是一个驱动程序问题(特别是因为这在 SQLServer 上运行良好)。您使用的是什么版本的 Oracle 驱动程序?你试过不同的版本吗?

于 2010-10-01T12:10:57.883 回答
0

我没有将所有DATE字段都转换为字段TIMESTAMP。相反,我扩展了 Oracle 的方言来重写该hour功能。

像那样:

public class Oracle9Dialect extends org.hibernate.dialect.Oracle9Dialect
{
    public Oracle9Dialect()
    {
        super();
        registerFunction("hour", new SQLFunctionTemplate(Hibernate.INTEGER, "to_number(to_char(?1, 'hh24'))"));
    }
}

使用这种方言 ( org.hibernate.dialect.Dialect),该hour函数将不使用 ANSIhour函数 ( extract(hour from <FIELD>))。它将to_number(to_char(<FIELD>, 'hh24'))改为使用。

不好的是它总是使用自定义函数(即使不需要使用它,比如使用TIMESTAMP字段)。

这就是我为解决我的问题所做的。

于 2010-10-04T14:15:52.733 回答