IN 表达式中的 JPQL LOWER 函数
Posted
技术标签:
【中文标题】IN 表达式中的 JPQL LOWER 函数【英文标题】:JPQL LOWER Function in IN Expression [duplicate] 【发布时间】:2018-07-17 22:40:09 【问题描述】:是否可以在 JPQL 中对 IN
表达式执行字符串函数,例如 LOWER
?
我正在尝试使用与此类似的 JPQL 查询(为简洁起见,查询已被简化):
SELECT e from MyEntity e WHERE LOWER(e.myAttribute) IN (LOWER(?1))
但是,对于 Hibernate/Oracle,这样的查询会导致类似于以下的错误:
WARN o.h.e.jdbc.spi.SqlExceptionHelper - SQL Error: 7001, SQLState: 07001
ERROR o.h.e.jdbc.spi.SqlExceptionHelper - Invalid parameter count for "LOWER", expected count: "1"; SQL statement:
select e.my_attribute from my_entity e where lower(e.my_attribute) in (lower(?, ?, ?)) [7001-197]
生成的 SQL 查询无效:
lower(e.my_attribute) in (lower(?, ?, ?))
我认为应该更像下面这样:
lower(e.my_attribute) in (lower(?), lower(?), lower(?))
我不清楚 JPA 规范是否可以将字符串函数应用于 IN
表达式,如果不能,那么合理的替代方案是什么。我使用IN
表达式而不是OR
,因为我的参数列表中有动态数量的项目,而我使用LOWER
是因为这些必须不区分大小写。
我正在使用 JPA 2.0/Hibernate 4.2/Oracle 11g/12c。不过,我宁愿避免使用任何特定于供应商的代码,并尽可能使用纯 JPA/JPQL。
【问题讨论】:
LOWER
采用单个字符串参数。参数1真的是String参数吗,如果是,为什么要使用IN
?!
@BillyFrost 参数 1 是字符串的列表。我需要将LOWER
字符串函数应用于每个列表项。
我找到了***.com/questions/9178290/…,这似乎与我的问题重复,并且似乎表明不区分大小写的IN
是不可能的。
并且你不能使用一个列表,而不是将每个列表分离成一个单独的参数......所以它们可以在 LOWER 中使用(它接受一个参数)。而另一个问题并没有“似乎表明”这是不可能的,它明确表示这是不可能的,因为你想要
【参考方案1】:
JPQL 正在按设计运行。它的解释是正确的,这就是在你的代码中定义函数和参数的方式。
IN (LOWER(?1))
子句声明将lower
函数应用于参数1
,在您的情况下是list
。因此您看到了错误。
要使用 Oracle 获得所需的结果,您可以使用内置的 Oracle 集合类型ODCIVARCHAR2LIST
。所以 JPQL 将如下所示:
SELECT e
FROM myentity e
WHERE Lower(e.myattribute) IN
(
SELECT Lower(column_value)
FROM table(sys.odcivarchar2list(?1)))
注意:对于 Oracle 12.2+,您不需要 table
函数,所以下面也可以:
SELECT e
FROM myentity e
WHERE Lower(e.myattribute) IN
(
SELECT Lower(column_value)
FROM sys.odcivarchar2list(?1))
【讨论】:
谢谢,@amith-kumar,但我希望避免在我的 JPQL 中出现供应商特定的内容。 是的,它确实成为了依赖于数据库的查询,但如果你真的想通过查询来实现它,它是一个选项。我个人更愿意将已经小写的列表作为参数传递给不区分大小写的 IN 搜索。以上是关于IN 表达式中的 JPQL LOWER 函数的主要内容,如果未能解决你的问题,请参考以下文章
JPQL 构造函数表达式 - org.hibernate.hql.ast.QuerySyntaxException:表未映射