Hel*_*rix 9 oracle spring hibernate spring-data spring-boot
我目前正在将 SpringBoot 2.7 应用程序迁移到 SpringBoot 3。在 SpringData 存储库中使用以下查询:
\n\n@Query("select b from #{#entityName} b where (trunc(b.date) <= trunc(:date))")\nList<T> findByDate(LocalDateTime date);\n\nRun Code Online (Sandbox Code Playgroud)\n虽然这在 SpringBoot 2.7 中效果很好,但在 SpringBoot 3 中会抛出以下消息:
\n\n\norg.hibernate.QueryException:函数 trunc() 的参数 1 的类型为 NUMERIC,但参数的类型为 java.time.LocalDateTime
\n
不幸的是,简单迁移到 datetrunc 并不成功:
\n\n\n错误消息 = ORA-00904: "DATETRUNC": ung\xc3\xbcltige ID
\n
有人有解决方案吗?
\n此致
\n因此,正如我在之前的回答中指出的那样,没有用于日期截断的标准 HQL 函数。这是因为在大多数 SQL 方言中实现起来相当困难(我还没有真正研究过有多难,但它至少很重要。)
然而,特别是对你来说,在今天应该进入 CR 的 Hibernate 6.2 中,我所做的是添加了对Postgres、DB2、Oracle 和 H2 下的功能的未记录的(但经过测试的)支持。当然date_trunc(),在 Oracle 上,这会转化为。trunc()
例如,你可以写:
date_trunc(year,current_timestamp)
Run Code Online (Sandbox Code Playgroud)
当我说它“无证”时,我的意思是您使用它的风险由您自己承担。(已记录的执行此操作的方法仍然是使用FunctionContributor。)
我希望这有帮助。
哦,顺便说一句,我刚刚注意到您实际上并没有trunc()在查询中使用该函数的完整形式。实际上,您只是剥离了时间戳的时间部分。
实际上,在 HQL 中有多种方法可以做到这一点,而无需使用 Oracle 特定的trunc()函数。(但是当然trunc()/date_trunc()可以做更多你在这里没有使用的事情。)
我在新的 JPA 3.1 规范中添加的改进之一是允许您编写:
extract(date from current_timestamp)
Run Code Online (Sandbox Code Playgroud)
去掉时间戳的时间部分。
cast()但如果您愿意,也可以使用 HQL 函数来完成此操作:
cast(current_timestamp as Date)
Run Code Online (Sandbox Code Playgroud)
这两个选项在 Oracle 上转换为相同的 SQL。
在 Hibernate 6 中,我们开始检查 HQL 函数的参数类型。\n由于它trunc(numeric,places)是跨多种 SQL 方言的非常常见的函数,因此我们将其注册为已知函数之一,尽管我们尚未将其提升为 \xe2\x80\ x9cstandard\xe2\x80\x9d HQL 函数(也许我们应该)。
另一方面,Oracle\xe2\x80\x99strunc(date)是 Oracle 特有的,更像是date_trunc()DB2 和 Postgres 上的功能。我们(到目前为止)还没有尝试标准化任何类型的时间戳截断函数,并且我不认为它是一个高优先级。此功能未由 注册OracleDialect。
因此,如果您尝试调用trunc()a Date,您将收到输入错误。
现在,一般来说,在 Hibernate 6.x 中:
\nDialect了解数据库中的每个 SQL 函数,并且您不能依赖这一点。trunc()不在该列表中,但它几乎进入了列表。)这完全没问题,因为我们还提供了 API,可以非常轻松地注册新的 SQL 函数,无论是像这样的特定于平台的函数,还是您自己编写的函数,方法如下:
\nDialect,或者FunctionContributor.或者,如果工作量太大,您可以使用 JPA 标准语法来调用本机 SQL 函数,即function(\'trunc\', date, \'YEAR\'),但我认为这有点不可爱。
| 归档时间: |
|
| 查看次数: |
6423 次 |
| 最近记录: |