为何JPA生成的SQL中IN子句会额外添加IN (NULL)?
JPA生成IN(NULL)的原因及修复方案
问题根源
你错误地嵌套调用了两次in方法:
代码中cb.in(root.get("zone").in(Arrays.asList("Zone 1")))这一行,root.get("zone").in(...)本身已经返回了一个用于IN查询的Predicate,但你额外将它传给CriteriaBuilder.in()方法,导致JPA错误地生成了嵌套IN的SQL结构——把第一个IN的结果再套入另一个无值的IN子句(默认补为IN(NULL)),最终导致查询无结果。
正确写法
有两种标准方式实现IN查询:
- 直接使用
Path.in()生成Predicate
Predicate[] predicates = new Predicate[] { root.get("zone").in(Arrays.asList("Zone 1")) };
- 使用
CriteriaBuilder.in()构建,需先传入目标字段,再添加查询值
// 单个值添加 Predicate[] predicates = new Predicate[] { cb.in(root.get("zone")).value("Zone 1").value("Zone 2") }; // 传入集合 Predicate[] predicates = new Predicate[] { cb.in(root.get("zone")).values(Arrays.asList("Zone 1", "Zone 2")) };
补充说明
CriteriaBuilder.in()方法接收的是一个Expression(即查询字段),而非已经构建好的Predicate。当你传入Path.in()返回的Predicate时,JPA会将其视为布尔表达式,但由于没有给cb.in()添加任何查询值,框架默认生成了IN(NULL)的无效子句,这就是问题的核心所在。
内容的提问来源于stack exchange,提问作者user2023141
相关产品推荐
相关产品推荐

