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

如何使用Criteria Query对无关联实体执行左外连接,实现旧SQL转JPA

无关联实体左外连接的Criteria Query实现方案

注:本实现仅支持JPA 2.1及以上版本,低版本JPA未提供无关联实体连接的标准支持,需使用原生SQL实现。

实现逻辑

原有SQL的核心是根据参数动态选择左关联A/B表,关联条件为两边id相等,由于Phone和A、B无实体关联映射,需要手动在join的on子句中指定关联规则。

完整代码示例

// 注入EntityManager实例
@PersistenceContext
private EntityManager entityManager;

public List<Object[]> getPhoneRelateData(boolean isA) {
    // 1. 构造Criteria基础对象
    CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
    // 定义返回值为Object数组,对应4个查询字段
    CriteriaQuery<Object[]> criteriaQuery = criteriaBuilder.createQuery(Object[].class);
    // 以Phone作为查询根节点
    Root<Phone> phoneRoot = criteriaQuery.from(Phone.class);

    // 2. 动态关联A/B实体,指定左外连接类型
    Join<?, ?> relateJoin;
    if (isA) {
        relateJoin = phoneRoot.join(A.class, JoinType.LEFT);
    } else {
        relateJoin = phoneRoot.join(B.class, JoinType.LEFT);
    }
    // 手动指定关联条件,对应原SQL的id匹配逻辑
    relateJoin.on(criteriaBuilder.equal(relateJoin.get("id"), phoneRoot.get("id")));

    // 3. 指定查询返回字段
    criteriaQuery.multiselect(
            phoneRoot.get("name"),
            phoneRoot.get("id"),
            relateJoin.get("name"),
            relateJoin.get("id")
    );

    // 4. 执行查询返回结果
    return entityManager.createQuery(criteriaQuery).getResultList();
}

补充说明

  • 原有SQL将关联条件写在where子句的写法存在逻辑问题:左外连接的关联条件放在where中会过滤关联表无匹配的行,实际等价于内连接。本实现将关联条件放在on子句中,完全符合左外连接语义,Phone表的全部数据都会保留,关联表无匹配时对应字段返回null。
  • 代码中get("属性名")的参数需要和对应实体类的属性名保持一致,无需和数据库列名匹配,JPA会自动根据实体的字段映射规则转换。
  • 如果需要封装为自定义DTO返回,可将CriteriaQuery的泛型改为对应DTO类,同时将multiselect替换为criteriaBuilder.construct(你的DTO类.class, 字段1, 字段2, 字段3, 字段4)即可。

内容的提问来源于stack exchange,提问作者Vidhya Raj Kaniyarakkal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 02:15:05