org.postgresql.util.PSQLException:错误:函数 lower(bytea)不存在

问题描述 投票:0回答:1

我正在从 javax 迁移到 jakarta。 我们的项目是使用 Spring Boot(因此从 2.7 升级到 3.2)和 Hibernate(5.6 到 6.3)构建的,并且我们使用 PostgreSQL 数据库(V14)。一个陷阱是自定义 PostgreSQL 方言的迁移,但我想我解决了令人满意的问题(-> 实现全文搜索条件)

当我们执行查询时出现主要问题:

      SELECT o FROM Order o
       WHERE (o.createdAt between :from and :to)
       AND (:query is null OR function('pgTextSearch', :query, o) = true)
       AND (:createdBy is null OR LOWER(o.createdBy) = LOWER(:createdBy))

它说:

引起:org.postgresql.util.PSQLException:错误:函数 lower(bytea) 不存在
注释:没有函数与给定的名称和参数类型匹配。您可能需要添加显式类型转换。

据我所知,这来自于以“null”作为参数调用 lower() 函数。 :createdBy 被声明为字符串(分别为 varchar)。在我的场景中, :createdBy 为 null,但这应该被第一个 OR 条件拦截。我错过了什么?

此外,我通过 PostgreSQL-CLI 使用替换参数执行查询,没有出现任何问题。

附注查询已针对迁移进行了修改,但仅限于自定义函数部分。
附言我阅读了 Spring Boot 和 Hibernate 的迁移指南(SQM 哎呀!),但找不到与我的用例有任何重叠的地方。
PPPS我没有手动设置参数(例如.setParameter("createdBy", xyz)),存储库是一个JpaRepository,因此参数替换是由Spring Data完成的

postgresql hibernate jpa lowercase named-parameters
1个回答
0
投票

短篇故事

你碰到了,10多年的老bug了:

说来话长

我。从 v6 开始,Hibernate 确实有一个 API 可以克服此类问题,例如:

    /**
     * Bind the given argument to a named query parameter using the given
     * Class reference to attempt to determine the {@link BindableType}
     * to use.  If unable to determine an appropriate {@link BindableType},
     * {@link #setParameter(String, Object)} is used.
     *
     * @see #setParameter(String, Object, BindableType)
     */
    <P> Query<R> setParameter(String parameter, P argument, Class<P> type);

不幸的是,您正在使用

spring-data-jpa
,而 Spring 团队尚未采用 Hibernate v6 的新功能 - 在这里我建议提交相应的 bug/cr。

二.看来特定查询的主要问题如下:

:createdBy
参数在
:createdBy is null OR LOWER(o.createdBy) = LOWER(:createdBy)
子句中出现两次,并且绝对没有选项可以从
:createdBy is null
表达式推断出正确的sql类型,但是,从技术上来说,应该可以从
varchar
推断出
LOWER(o.createdBy) = LOWER(:createdBy)
sql类型表达式,问题是 Hibernate 只尝试推断查询参数的 sql 类型一次,所以你会变得很奇怪
bytea
而不是
varchar
(这里我不知道为什么不将默认设置为更常见的东西而不是
bytea 
)。

你能尝试翻转

:createdBy is null
LOWER(o.createdBy) = LOWER(:createdBy)
表达式吗?我怀疑它可以解决问题。

三.编写此类“通用”查询的惯用方法是使用

SpEL
或 JPA 规范,请检查 Hibernate 随机抛出错误:无法强制值
[]
[java.util.ArrayList] as Long

© www.soinside.com 2019 - 2024. All rights reserved.