Java 使用Hibernate避免使用Oracle进行从日期到时间戳的隐式转换

Java 使用Hibernate避免使用Oracle进行从日期到时间戳的隐式转换,java,oracle,hibernate,Java,Oracle,Hibernate,我使用Hibernate 3.2.7.GA标准查询从Oracle Enterprise Edition 10.2.0.4.0数据库中选择行,并通过时间戳字段进行过滤。该字段在java中的类型为java.util.Date,在Oracle中的类型为Date 字段映射到java.sql.Timestamp,Oracle将所有行转换为Timestamp,然后与传入的值进行比较,从而破坏性能 一种解决方案是使用Hibernate的sqlRestriction()和Oracle的to_DATE函数。这将修

我使用Hibernate 3.2.7.GA标准查询从Oracle Enterprise Edition 10.2.0.4.0数据库中选择行,并通过时间戳字段进行过滤。该字段在java中的类型为
java.util.Date
,在Oracle中的类型为
Date

字段映射到
java.sql.Timestamp
,Oracle将所有行转换为
Timestamp
,然后与传入的值进行比较,从而破坏性能

一种解决方案是使用Hibernate的
sqlRestriction()
和Oracle的
to_DATE
函数。这将修复性能,但需要重写应用程序代码(大量查询)

那么有没有更优雅的解决方案?既然Hibernate已经进行了类型映射,那么是否可以将其配置为执行正确的操作

更新:问题出现在各种配置中,但这里有一个具体示例:

  • Oracle企业版10.2.0.4.0
  • Oracle JDBC驱动程序11.1.0.7.0
  • Hibernate 3.2.7.GA
  • Hibernate的Oracle10g方言
  • Java 1.6.0_16

这听起来可能有点过激,但当遇到这个问题时,我们最终将数据库中的所有日期列转换为时间戳类型。我看不出这有什么缺点,如果Hibernate是您的主要应用程序平台,那么您将避免将来的麻烦

注:

  • 列类型可以通过以下方式更改: 一个简单的“altertablename”修改 columnName时间戳(precisionVal)”

  • 我惊讶地发现这一点 这些列上的内容不必是
    重建


同样,这只有在您致力于Hibernate时才有意义。

这听起来可能很激烈,但当遇到这个问题时,我们最终将数据库中的所有日期列转换为时间戳类型。我看不出这有什么缺点,如果Hibernate是您的主要应用程序平台,那么您将避免将来的麻烦

注:

  • 列类型可以通过以下方式更改: 一个简单的“altertablename”修改 columnName时间戳(precisionVal)”

  • 我惊讶地发现这一点 这些列上的内容不必是
    重建

同样,只有当您致力于休眠时,这才有意义。

根据:

“11.1从数据库读取数据时,驱动程序默认将SQL日期转换为时间戳”

因此,这是一种预期行为。 对我来说,这意味着来自
DATE
列的实际值将转换为
java.sql.Timestamp
,而不是将带有
java.util.DATE
的绑定变量转换为
java.sql.Timestamp

解释计划
输出将有助于识别问题。此外,Oracle跟踪可以准确地告诉您在查询中为bind变量分配了什么类型

如果这种情况真的发生,那可能是甲骨文的错误

您可以通过以下方式解决此问题:

  • 日期
    列上创建一个FBI(),将其转换为
    时间戳
    。例如:

    CREATE INDEX tab_idx ON tab (CAST(date_col AS TIMESTAMP)) COMPUTE STATISTICS;
    
  • 创建包含相同
    CAST
    表达式的视图。如果需要,可以保留相同的列名:

    CREATE VIEW v AS
    SELECT CAST(date_col AS TIMESTAMP) AS date_col, col_1, ... FROM tab;
    
  • 使用视图而不是表(这通常是一个好主意,例如,如果您已经在使用视图,则根本不需要更改代码)。当
    java.sql.Timestamp
    变量将在
    WHERE
    条件下与
    date\u col
    一起使用时,(如果选择足够多),将使用索引

  • 如果您发现了为什么会出现
    java.sql.Timestamp
    (或者Oracle修复了潜在的bug),您可以随时返回,只需更改视图(并删除FBI),它对代码是完全透明的

根据:

“11.1从数据库读取数据时,驱动程序默认将SQL日期转换为时间戳”

因此,这是一种预期行为。 对我来说,这意味着来自
DATE
列的实际值将转换为
java.sql.Timestamp
,而不是将带有
java.util.DATE
的绑定变量转换为
java.sql.Timestamp

解释计划
输出将有助于识别问题。此外,Oracle跟踪可以准确地告诉您在查询中为bind变量分配了什么类型

如果这种情况真的发生,那可能是甲骨文的错误

您可以通过以下方式解决此问题:

  • 日期
    列上创建一个FBI(),将其转换为
    时间戳
    。例如:

    CREATE INDEX tab_idx ON tab (CAST(date_col AS TIMESTAMP)) COMPUTE STATISTICS;
    
  • 创建包含相同
    CAST
    表达式的视图。如果需要,可以保留相同的列名:

    CREATE VIEW v AS
    SELECT CAST(date_col AS TIMESTAMP) AS date_col, col_1, ... FROM tab;
    
  • 使用视图而不是表(这通常是一个好主意,例如,如果您已经在使用视图,则根本不需要更改代码)。当
    java.sql.Timestamp
    变量将在
    WHERE
    条件下与
    date\u col
    一起使用时,(如果选择足够多),将使用索引

  • 如果您发现了为什么会出现
    java.sql.Timestamp
    (或者Oracle修复了潜在的bug),您可以随时返回,只需更改视图(并删除FBI),它对代码是完全透明的


我认为这取决于您使用的驱动程序(版本)(请参阅和您提供的链接)以及可能的方言。请澄清两者。谢谢Pascal,我用具体版本澄清了这个问题。我认为这取决于您使用的驱动程序(版本)(请参阅和您提供的链接)以及可能的方言。请澄清两者。谢谢帕斯卡,我用具体的版本澄清了这个问题。缩小尺寸是你的空间需求的两倍多。日期需要8个字节,而时间戳需要20个字节-