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

如何使用Hibernate Criteria实现跨两表的OR查询?

跨表匹配cdDocumentoIdentificativo的Criteria查询实现

先明确你的问题核心

你需要基于cdDocumentoIdentificativo字段,查询主实体中关联的Owners表或Sellers表里Person记录匹配该字段的所有条目。先指出你两次尝试的问题:

  • 第一种尝试:子查询的关联逻辑混乱,别名使用错误,且条件用了isNotNull而非字段匹配,完全偏离需求。
  • 第二种尝试:属性路径错误(比如owner.own.person这种嵌套逻辑不对),且硬编码了字符串常量,没有使用实际的过滤值。

正确实现方式(分两种场景)

假设你的主查询实体是MainEntity(比如订单、合同这类关联了Owner和Seller的业务实体),且MainEntity与Owner、Seller是一对多或多对多关联,Owner/Seller都关联了Person实体,Person包含cdDocumentoIdentificativo字段。

方式1:直接关联+OR条件查询

这是最直观的方式,通过创建别名关联到Person表,然后组合两个匹配条件:

String docId = (String) this.getFiltros().get("cdDocumentoIdentificativo");
if (docId != null && !docId.isEmpty()) {
    // 为Owner关联的Person创建别名
    query.createAlias("owners", "own");
    query.createAlias("own.person", "ownerPerson");
    
    // 为Seller关联的Person创建别名
    query.createAlias("sellers", "sell");
    query.createAlias("sell.person", "sellerPerson");
    
    // 组合OR条件:匹配Owner的Person或Seller的Person的cdDocumentoIdentificativo
    Criterion ownerMatch = Restrictions.eq("ownerPerson.cdDocumentoIdentificativo", docId);
    Criterion sellerMatch = Restrictions.eq("sellerPerson.cdDocumentoIdentificativo", docId);
    query.add(Restrictions.or(ownerMatch, sellerMatch));
}

注意:如果主实体与Owner/Seller是一对多关联,可能需要使用左连接模式避免数据丢失:

query.createAlias("owners", "own", JoinType.LEFT_OUTER_JOIN);
query.createAlias("sellers", "sell", JoinType.LEFT_OUTER_JOIN);

方式2:子查询+EXISTS条件

如果不想直接关联多张表(避免笛卡尔积),可以用子查询分别判断Owner或Seller是否存在匹配记录:

String docId = (String) this.getFiltros().get("cdDocumentoIdentificativo");
if (docId != null && !docId.isEmpty()) {
    // 子查询1:查询匹配cdDocumentoIdentificativo的Owner对应的主实体ID
    DetachedCriteria ownerSubquery = DetachedCriteria.forClass(Owner.class, "own");
    ownerSubquery.createAlias("own.person", "p");
    ownerSubquery.add(Restrictions.eq("p.cdDocumentoIdentificativo", docId));
    ownerSubquery.setProjection(Projections.property("own.mainEntity.id")); // 假设Owner关联主实体的字段是mainEntity
    
    // 子查询2:查询匹配cdDocumentoIdentificativo的Seller对应的主实体ID
    DetachedCriteria sellerSubquery = DetachedCriteria.forClass(Seller.class, "sell");
    sellerSubquery.createAlias("sell.person", "p");
    sellerSubquery.add(Restrictions.eq("p.cdDocumentoIdentificativo", docId));
    sellerSubquery.setProjection(Projections.property("sell.mainEntity.id"));
    
    // 主查询添加OR条件:主实体ID存在于任一子查询结果中
    query.add(Restrictions.or(
        Subqueries.propertyIn("id", ownerSubquery),
        Subqueries.propertyIn("id", sellerSubquery)
    ));
}

关键注意点

  • 确保实体类的关联映射正确(比如Owner类中person字段的@ManyToOne/@OneToOne注解,MainEntity中owners/sellers的@OneToMany注解)。
  • 属性路径必须严格对应实体类的字段名,比如own.person对应的是Owner类中名为person的属性,而非数据库表字段名。
  • 过滤值要使用变量docId,而非硬编码的字符串"cdDocumentoIdentificativo"。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 10:15:28