You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

javax.persistence.criteria.CriteriaBuilder#or工作原理及无返回结果问题咨询

问题根因

你遇到的这个现象由两个错误共同导致:

  1. 隐式内连接过滤了有效数据
    你通过root.get("a").get("b").get("y")这种连续调用获取属性路径的写法,JPA CriteriaAPI 会默认生成INNER JOIN关联对应实体。只要任意X实例的c属性为空、或c关联的d属性为空,这条实例在执行关联时就会被提前排除,哪怕它满足p1的匹配条件也不会进入后续的谓词判断环节。
    单独使用p1时只会生成a、b的内连接,只要这两个关联不为空且y值匹配就能返回结果;一旦你用到了path2的路径,不管你用or还是and组合条件,都会额外生成c、d的内连接,把c/d为空的有效行直接过滤,最终导致or组合后无结果返回。
  2. 查询相关对象作为单例Bean的成员变量,存在线程安全问题
    Spring 中@Repository注解的Bean默认是单例模式,你把CriteriaBuilder、CriteriaQuery、Root这些对象定义为类成员变量,只会在Bean初始化时创建一次,每次调用filter方法都会复用同一个query对象,多次调用会叠加where条件,会出现各种不可预期的查询结果。

修复方案

1. 手动指定左连接替代隐式内连接

把连续get属性的写法改为手动构造左连接,避免关联为空时提前过滤数据:

// 每次查询重新构造join,不要复用
Join<X, A> aJoin = root.join("a", JoinType.LEFT);
Join<A, B> bJoin = aJoin.join("b", JoinType.LEFT);
Expression<?> path1 = bJoin.get("y");

Join<X, C> cJoin = root.join("c", JoinType.LEFT);
Join<C, D> dJoin = cJoin.join("d", JoinType.LEFT);
Expression<?> path2 = dJoin.get("y");

2. 每次查询重新创建查询相关对象

不要把CriteriaQuery、Root作为类成员变量,每次调用filter方法时重新创建,保证每次查询独立且线程安全,修改后的代码示例如下:

@Repository
public class CustomXRepositoryImpl implements CustomXRepository {

    private final EntityManager em;

    @Autowired
    public CustomXRepositoryImpl(EntityManager em) {
        this.em = em;
    }

    @Override
    public List<X> filter(FilterParams params) {
        CriteriaBuilder builder = em.getCriteriaBuilder();
        CriteriaQuery<X> query = builder.createQuery(X.class);
        Root<X> root = query.from(X.class);
        List<Predicate> restrictions = new ArrayList<>();
        
        // 条件逻辑
        if (params.getY() != null) {
            // 此处插入上面的左连接构造逻辑
            Predicate p1 = builder.equal(path1, params.getY());
            Predicate p2 = builder.equal(path2, params.getY());
            restrictions.add(builder.or(p1, p2));
        }
        
        // 其余条件逻辑不变
        query.where(restrictions.toArray(new Predicate[0]));
        return em.createQuery(query).getResultList();
    }
}

内容的提问来源于stack exchange,提问作者dr1be

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 09:15:04