QueryDSL 子查询不起作用 - IllegalArgumentException:参数值与预期类型不匹配

Posted

技术标签:

【中文标题】QueryDSL 子查询不起作用 - IllegalArgumentException:参数值与预期类型不匹配【英文标题】:QueryDSL SubQuery not working - IllegalArgumentException: Parameter value did not match expected type 【发布时间】:2018-02-20 05:46:32 【问题描述】:

我正在尝试使用 QueryDSL 4.1.4 中的子查询运行查询。 3.x 版中的等价物可以工作,但我似乎无法让它在 4.1.4 版中工作。不确定我是否遗漏了什么或是否有错误。任何意见表示赞赏!

以下是相关代码:

PathBuilder productEntity = ...;
PathBuilder categoryEntity = ...;

JPQLQuery query = queryFactory.get().query();
query.distinct();

FilteredClause subQuery = JPAExpressions
    .select(productEntity.get("id", Long.class))
    .from(categoryEntity)
    .innerJoin(categoryEntity.get("products"), productEntity)
    .where(categoryEntity.get("id", Long.class).eq(categoryId));

query.where(productEntity.get("id", Long.class).notIn(subQuery));
query.fetch();

通过上述,我得到以下异常:

java.lang.IllegalArgumentException: Parameter value [select product.id
from Category category
  inner join treat(category.products as Product) as product
where category.id = ?1] did not match expected type [java.lang.Long (n/a)]
    at org.hibernate.jpa.spi.BaseQueryImpl.validateBinding(BaseQueryImpl.java:897)
    at org.hibernate.jpa.internal.QueryImpl.access$000(QueryImpl.java:61)
    at org.hibernate.jpa.internal.QueryImpl$ParameterRegistrationImpl.bindValue(QueryImpl.java:235)
    at org.hibernate.jpa.internal.QueryImpl$JpaPositionalParameterRegistrationImpl.bindValue(QueryImpl.java:371)
    at org.hibernate.jpa.spi.BaseQueryImpl.setParameter(BaseQueryImpl.java:692)
    at org.hibernate.jpa.spi.AbstractQueryImpl.setParameter(AbstractQueryImpl.java:181)
    at org.hibernate.jpa.spi.AbstractQueryImpl.setParameter(AbstractQueryImpl.java:32)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:372)
    at com.sun.proxy.$Proxy365.setParameter(Unknown Source)
    at com.querydsl.jpa.impl.JPAUtil.setConstants(JPAUtil.java:56)
    at com.querydsl.jpa.impl.AbstractJPAQuery.createQuery(AbstractJPAQuery.java:102)
    at com.querydsl.jpa.impl.AbstractJPAQuery.fetchCount(AbstractJPAQuery.java:81)
...

似乎整个子查询都设置为参数,而 Hibernate 对此并不满意。我应该使用不同的 QueryDSL 语法来避免这个问题吗?

【问题讨论】:

【参考方案1】:

我发现问题出在FilteredClause 类型的子查询上。它没有导致任何编译错误,因此可能是 Querydsl 可以更好地处理的事情,但是在将子查询更改为以下内容后开始工作:

JPQLQuery subQuery = JPAExpressions
    .select(productEntity.get("id", Long.class))
    .from(categoryEntity)
    .innerJoin(categoryEntity.get("products"), productEntity);

// Keep the .where() call separate to retain the JPQLQuery object
subQuery.where(categoryEntity.get("id", Long.class).eq(categoryId));

// subQuery is now of type JPQLQuery instead of FilteredClause
query.where(productEntity.get("id", Long.class).notIn(subQuery));

List result = query.fetch();

【讨论】:

以上是关于QueryDSL 子查询不起作用 - IllegalArgumentException:参数值与预期类型不匹配的主要内容,如果未能解决你的问题,请参考以下文章

子查询中的子查询在配置单元中不起作用

子查询不起作用

当相关子查询不起作用时,压缩子查询

Oracle SQL - 多级相关子查询不起作用

查询显示子文档不起作用

为啥我的 Access Max() 子查询不起作用?