为什么此 JPA 查询在 H2 数据库上失败?
Why does this JPA query fail on a H2 database?
我在 Spring 数据接口
中定义了以下 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);
但这没有什么区别,我仍然得到同样的错误。
这是由 org.hibernate.dialect.H2Dialect.
中的错误引起的
如果您传递一个空集作为查询参数值,它构成 JPQL 查询中“不在”谓词的右侧,则当 运行 针对 H2 数据库时查询失败。要解决此问题,请使用包含
取而代之的是单个空元素。
例如在你调用这个查询的地方使用
UUID taskId = UUID.randomUUID();
Set<String> supplierIds = // get this from somewhere
if (supplierIds.isEmpty()) {
supplierIds.add(null);
}
myRepository.supplierIdsDueTaskRevocationNotification(taskId, supplierIds)
我在 Spring 数据接口
中定义了以下 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);
但这没有什么区别,我仍然得到同样的错误。
这是由 org.hibernate.dialect.H2Dialect.
中的错误引起的如果您传递一个空集作为查询参数值,它构成 JPQL 查询中“不在”谓词的右侧,则当 运行 针对 H2 数据库时查询失败。要解决此问题,请使用包含 取而代之的是单个空元素。
例如在你调用这个查询的地方使用
UUID taskId = UUID.randomUUID();
Set<String> supplierIds = // get this from somewhere
if (supplierIds.isEmpty()) {
supplierIds.add(null);
}
myRepository.supplierIdsDueTaskRevocationNotification(taskId, supplierIds)