如何用Criteria Builder实现SQL多条件组合排除逻辑?
问题解答
你的Criteria Builder代码无法实现与目标SQL一致的逻辑,具体问题和修正方案如下:
原SQL逻辑解析
目标SQL的条件是:
NOT(request_type = 'SELF_SERVICE' and enquiry_status_id = 19)
它的含义是:排除所有同时满足request_type = 'SELF_SERVICE'且enquiry_status_id = 19的记录,根据德摩根定律,等价于:
request_type != 'SELF_SERVICE' OR enquiry_status_id != 19
你的代码存在的问题
你当前的代码构造的条件是:
cb.equal(enquiryRoot.get("requestType"), "SELF_SERVICE") AND cb.notEqual(enquiryRoot.get("status").get("id"), 19)
这表示筛选request_type = 'SELF_SERVICE'且enquiry_status_id != 19的记录,和原SQL的排除逻辑完全相反,范围完全不同。
正确的实现方式
有两种等价的写法可以匹配原SQL的逻辑:
写法一:直接使用cb.not()包裹原组合条件
CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<Enquiry> query = cb.createQuery(Enquiry.class); Root<Enquiry> enquiryRoot = query.from(Enquiry.class); // 构造原SQL中的内部条件:request_type = 'SELF_SERVICE' AND enquiry_status_id = 19 Predicate selfServiceAndStatus19 = cb.and( cb.equal(enquiryRoot.get("requestType"), "SELF_SERVICE"), cb.equal(enquiryRoot.get("status").get("id"), 19) ); // 用NOT包裹该条件,实现原SQL的排除逻辑 query.where(cb.not(selfServiceAndStatus19));
写法二:利用德摩根定律转成OR条件
CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<Enquiry> query = cb.createQuery(Enquiry.class); Root<Enquiry> enquiryRoot = query.from(Enquiry.class); // 等价于 NOT(A AND B) = NOT A OR NOT B Predicate notSelfService = cb.notEqual(enquiryRoot.get("requestType"), "SELF_SERVICE"); Predicate notStatus19 = cb.notEqual(enquiryRoot.get("status").get("id"), 19); query.where(cb.or(notSelfService, notStatus19));
两种写法生成的SQL逻辑和你目标的查询完全一致,可以根据习惯选择使用。
内容的提问来源于stack exchange,提问作者Teong
相关产品推荐
相关产品推荐

