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

使用Criteria API查询关联AEntity名称包含指定全部值的BEntity

实现方案

核心思路

你用in表达式只能匹配到关联了任意一个目标AEntity的BEntity,无法实现全匹配。正确的做法是:

  1. 关联BEntity和AEntity的多对多关系
  2. 过滤出AEntity名称在目标列表中的记录
  3. 按BEntity主键分组
  4. 统计每个BEntity匹配到的AEntity数量,只有数量等于目标列表长度的才是同时包含所有目标AEntity的记录

完整Criteria API实现代码

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.criteria.*;
import org.springframework.stereotype.Repository;
import java.util.Collections;
import java.util.List;

@Repository
public class BRepositoryImpl {

    @PersistenceContext
    private EntityManager entityManager;

    public List<BEntity> mySearchMethod(List<String> targetANameList) {
        // 边界处理:空列表可根据业务需求调整返回逻辑
        if (targetANameList == null || targetANameList.isEmpty()) {
            return Collections.emptyList();
        }

        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        CriteriaQuery<BEntity> query = cb.createQuery(BEntity.class);
        Root<BEntity> bRoot = query.from(BEntity.class);
        // 内连接关联AEntity集合
        Join<BEntity, AEntity> aJoin = bRoot.join("aEntities", JoinType.INNER);

        // 过滤名称在目标列表的AEntity
        Predicate nameInPredicate = aJoin.get("name").in(targetANameList);

        query.where(nameInPredicate)
                // 按BEntity主键分组
                .groupBy(bRoot.get("id"))
                // 匹配到的A数量等于目标列表长度,说明包含所有目标A
                .having(cb.equal(cb.countDistinct(aJoin.get("id")), targetANameList.size()));

        return entityManager.createQuery(query).getResultList();
    }
}

实现原理

拿你的示例数据举例,传入目标列表["A1", "A3"]:

  1. 内连接后会把每个B和关联的A拆分为独立行:B1-A1、B1-A2、B1-A3、B2-A1、B2-A3、B3-A3
  2. 经过where过滤后剩下:B1-A1、B1-A3、B2-A1、B2-A3、B3-A3
  3. 按B的id分组后,各组匹配到的A数量分别为:B1=2、B2=2、B3=1
  4. having筛选数量等于2的分组,最终返回B1和B2,完全符合预期

补充说明

  1. 如果AEntity的name不唯一,建议先根据name列表查询到对应的AEntity主键集合,再用主键做in查询和计数,避免计数错误
  2. 如果使用Spring Data JPA,也可以直接用JPQL实现,逻辑完全一致:
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;

public interface BRepository extends JpaRepository<BEntity, Long> {
    @Query("SELECT b FROM BEntity b JOIN b.aEntities a WHERE a.name IN :names GROUP BY b.id HAVING COUNT(DISTINCT a.id) = :#{#names.size()}")
    List<BEntity> mySearchMethod(@Param("names") List<String> targetANameList);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 08:24:06