如何用JPA Criteria Builder构建ORDER BY NOT IN排序查询
JPA Criteria Builder 实现带NOT IN逻辑的ORDER BY查询
你要实现的排序逻辑核心是把id NOT IN (子查询结果集)这个布尔判断作为排序表达式,按降序排列即可,最终生成的SQL和你给出的目标语句逻辑完全一致。
实现代码
先做实体映射假设:
- 主表对应实体类为
Transaction,主键属性为id,对应SQL里的$table_name - 子表对应实体类为
TransactionRelation,关联属性为transactionId,对应SQL里的$child_table
完整实现代码如下:
// 初始化Criteria查询上下文 CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<Transaction> cq = cb.createQuery(Transaction.class); Root<Transaction> mainRoot = cq.from(Transaction.class); // 构建子查询:查出子表中所有非空的transaction_id Subquery<Long> childIdSubQuery = cq.subquery(Long.class); Root<TransactionRelation> subRoot = childIdSubQuery.from(TransactionRelation.class); childIdSubQuery.select(subRoot.get("transactionId")) .where(cb.isNotNull(subRoot.get("transactionId"))); // 构建排序规则:id不在子查询结果中的记录优先返回(降序排列时布尔值true在前) Expression<Boolean> sortExpr = cb.not(mainRoot.get("id").in(childIdSubQuery)); cq.select(mainRoot).orderBy(cb.desc(sortExpr)); // 执行查询 List<Transaction> resultList = entityManager.createQuery(cq).getResultList();
注意事项
- 代码中
get()方法传入的是实体类的属性名,不是数据库表的列名,需要和你自己项目里的JPA实体定义保持一致 - 如果你的主键id是String、UUID等非Long类型,只需要修改Subquery的泛型为对应类型即可,核心逻辑不需要调整
- 主流数据库(MySQL、PostgreSQL、Oracle等)对布尔表达式排序的规则一致:降序时
true排在false前面,正好匹配你要的排序效果;Hibernate 5.2+、EclipseLink 2.7+等常用JPA实现都原生支持该写法,不会生成语法错误的SQL
内容的提问来源于stack exchange,提问作者ragilGM
相关产品推荐
相关产品推荐

