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

如何用Hibernate CriteriaBuilder实现无外键的IN子查询

使用CriteriaBuilder实现子查询IN条件查询

实体类定义

@Entity
public class Thing1 {
  @Column
  long id;

  @Column
  String someReference;
}

@Entity
public class Thing2 {
  @EmbeddedId
  Thing2PK id;

  @Embeddable
  public static class Thing2PK implements Serializable
  {
    @Column
    private String name;

    @Column(name = "client_id")
    private String account;

    @Column
    String possibleReference;
  }
}

需求SQL

需要构建如下原生SQL对应的Criteria查询:

SELECT *
FROM thing1
WHERE someReference IN (
 SELECT possibleReference 
 FROM thing2
 WHERE name = :name)

问题

尝试使用criteriaBuilder.in时,发现它需要值集合或带@JoinColumn的关联查询,当前场景无法满足,该如何实现?


解决方案

可以通过**子查询(Subquery)**来实现这个IN条件,具体代码如下:

// 获取CriteriaBuilder
CriteriaBuilder cb = entityManager.getCriteriaBuilder();

// 1. 构建主查询:查询Thing1的所有数据
CriteriaQuery<Thing1> mainQuery = cb.createQuery(Thing1.class);
Root<Thing1> thing1Root = mainQuery.from(Thing1.class);
mainQuery.select(thing1Root);

// 2. 构建子查询:从Thing2中查询符合条件的possibleReference
Subquery<String> subQuery = mainQuery.subquery(String.class);
Root<Thing2> thing2Root = subQuery.from(Thing2.class);
subQuery.select(thing2Root.get("id").get("possibleReference")); // 关联嵌入式ID中的字段
subQuery.where(cb.equal(thing2Root.get("id").get("name"), cb.parameter(String.class, "name")));

// 3. 主查询添加IN条件:someReference在子查询结果中
mainQuery.where(cb.in(thing1Root.get("someReference")).value(subQuery));

// 执行查询
TypedQuery<Thing1> query = entityManager.createQuery(mainQuery);
query.setParameter("name", "目标名称");
List<Thing1> resultList = query.getResultList();

关键说明

  • 子查询的返回类型要和主查询中用来匹配的字段类型一致(这里都是String)
  • 访问嵌入式ID的字段时,需要通过root.get("id")先获取嵌入式ID对象,再进一步获取其中的属性(如name、possibleReference)
  • 如果使用JPA元模型(Metamodel),可以替换字符串字段名为强类型的属性,比如Thing2_.id.get(Thing2PK_.possibleReference),避免硬编码错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 12:15:32