为啥这个 JPA 查询在 H2 数据库上失败?
Posted
技术标签:
【中文标题】为啥这个 JPA 查询在 H2 数据库上失败?【英文标题】:Why does this JPA query fail on a H2 database?为什么这个 JPA 查询在 H2 数据库上失败? 【发布时间】:2022-01-19 16:41:57 【问题描述】:我在 Spring Data 接口中定义了以下 JPA 查询
@Query("select tr.bidder.supplierId " +
"from TaskResponse tr " +
"where tr.task.id = :taskId " +
"and tr.extended = true " +
"and tr.bidder.supplierId not in (:extendedSupplierIds)")
Set<String> supplierIdsDueTaskRevocationNotification(UUID taskId,
Set<String> extendedSupplierIds);
查询在对 Postgres 数据库执行时工作正常,但在对 H2 数据库执行时失败并出现以下错误:
Syntax error in SQL statement
SELECT BIDDER1_.SUPPLIER_ID AS COL_0_0_
FROM TASK_RESPONSES TASKRESPON0_
CROSS JOIN BIDDERS BIDDER1_
WHERE TASKRESPON0_.BIDDER_ID=BIDDER1_.ID
AND TASKRESPON0_.TASK_ID=?
AND TASKRESPON0_.EXTENDED=1
AND (BIDDER1_.SUPPLIER_ID NOT IN ()[*])";
expected "NOT, EXISTS, INTERSECTS, UNIQUE";
看起来问题出在not in (:extendedSupplierIds)
谓词上,因为如果我删除这个谓词,查询在两个数据库上执行时都不会出错。
有没有办法我可以重写查询,以便它可以在两个数据库上工作?
更新
根据一位受访者的建议,我将查询更改为使用显式联接
@Query("select b.supplierId " +
"from TaskResponse tr " +
"join tr.bidder b " +
"join tr.task t " +
"where t.id = :taskId " +
"and tr.extended = true " +
"and b.supplierId not in (:extendedSupplierIds)")
Set<String> supplierIdsDueTaskRevocationNotification(UUID taskId,
Set<String> extendedSupplierIds);
但这并没有什么不同,我仍然得到同样的错误。
【问题讨论】:
您是否也将方言更改为 H2Dialect? @Turo 是的,我做到了 两个数据库发出的SQL是什么?为 :extendedSupplierIds 传递了什么,并且由于它是一个集合,“tr.bidder.supplierId 不在 :extendedSupplierIds”中是否有效或没有括号有效?似乎很奇怪,错误不会显示带有一系列“?”的 SQL 语句。括号之间 【参考方案1】:这是由错误引起的,可能在 org.hibernate.dialect.H2Dialect 中。
如果您将空集作为查询参数值传递,该值构成 JPQL 查询中“不在”谓词的右侧,则在针对 H2 数据库运行时查询会失败。要解决此问题,请使用 Set 包含 而是一个空元素。
例如在您调用此查询时使用
UUID taskId = UUID.randomUUID();
Set<String> supplierIds = // get this from somewhere
if (supplierIds.isEmpty())
supplierIds.add(null);
myRepository.supplierIdsDueTaskRevocationNotification(taskId, supplierIds)
【讨论】:
以上是关于为啥这个 JPA 查询在 H2 数据库上失败?的主要内容,如果未能解决你的问题,请参考以下文章
使用 JPA (Eclipselink) 在 H2 数据库中执行全文搜索
H2 查询失败,“节点没有数据类型:org.hibernate.hql.internal.ast.tree.MethodNode”