JPA中Join<A,B>调用Path.get("ID")返回B的ID而非A的ID是什么原因?
问题原因
你的错误非常直接,根源在于ID字段所属的路径对象选择错误:
itemPropertiesJoin是Join<CustomerItem, Item>类型,对应的是关联的Item实体,所以你调用itemPropertiesJoin.<Integer>get(ID)时,拿到的自然是Item表的主键,对应你SQL里的t10.ID- 如果你要获取源表
mp_customer_item的ID,应该从子查询的根对象itemProperties(类型为Root<CustomerItem>)获取,也就是itemProperties.get(ID),这个路径才对应表别名t11的主键字段。
另外你代码里存在一处多余的重复配置:你已经单独调用过subquery.select(...)设置返回字段,后面构造in谓词时又调用了一次subquery.select(itemProperties.get(ID)),按JPA Criteria规范,后面的select调用会覆盖之前的配置。如果你实际生成的SQL还是返回Item的ID,说明你运行的代码可能和你贴出的版本有偏差,没有触发后面的覆盖逻辑。
修复方案
调整后的子查询代码参考:
Subquery<Integer> subquery = criteriaQuery.subquery(Integer.class); Root<CustomerItem> itemProperties = subquery.from(CustomerItem.class); // 不需要fetch的话直接用join,避免强转,需要fetch的话可以保留原来的写法 Join<CustomerItem, Item> itemPropertiesJoin = itemProperties.join(ITEM); itemPropertiesJoin.get(ITEM_PROPERTIES).in(ecoLabelHelper.getEcoProperties(filterCriteria.getCustomer())); // 直接选择CustomerItem的ID,只设置一次select即可 subquery.select(itemProperties.get(ID)); subquery.distinct(true); Predicate itemIsNotEco = criteriaBuilder.not(criteriaBuilder.in(root.get(ID)).value(subquery)); conditions.add(criteriaBuilder.and(itemIsNotEco, customerItemIsEco.not()));
修复后生成的SQL就会返回t11.ID也就是CustomerItem的主键了。
内容的提问来源于stack exchange,提问作者Jssson
相关产品推荐
相关产品推荐

