使用 JPA Criteria API 为 joined table 添加 where 子句

Add where clause for joined table with JPA Criteria API

我在 vocab 和 vocabml 之间有一个一对多的关联,

简单查询需要做什么(连接两张表,根据描述条件过滤):

select  * from vocab v
left join vocabml vm on vm.vocabid = v.id and vm.locale in ('uk','en'....)
where v.description like '%syst%'
or vm.description like '%syst%'

我对标准 API 的尝试引发异常:Caused by: java.lang.IllegalStateException: Illegal attempt to dereference path source [null.vocabmls] of basic type

我的代码:

CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Vocab> criteriaQuery = builder.createQuery(Vocab.class);
criteriaQuery.distinct(true);

Root<Vocab> root = criteriaQuery.from(Vocab.class);
root.fetch("vocabmls", JoinType.LEFT);

List<Predicate> predicates = = new ArrayList<>();


Predicate predicate = builder.or(builder.like(root.get("description"), "%" + description + "%"),
                      builder.like(root.get("vocabmls").get("description"), "%" + description + "%"));
predicates.add(predicate)

if(locales != null){
    List<String> ids = locales.stream().map(Locale::getId).collect(Collectors.toList());
    Join<Vocab, Vocabml> vocabmlJoin = root.join("vocabmls", JoinType.LEFT);
    vocabmlJoin.on(builder.and(vocabmlJoin.<Vocabml> get("localeId").in(ids)));
}

criteriaQuery.where(predicates.toArray(new Predicate[] {})).orderBy(builder.asc(root.get("description")));
return entityManager.createQuery(criteriaQuery).getResultList();

我是这样解决的,需要用join添加条件

Predicate predicateJoin = builder.equal(vocabmlJoin.get("description"), description);
predicates.add(predicateJoin);

它将简单地添加 where vm.description =

我还把这个改成了 OR not AND

 criteriaQuery.where(builder.or(predicates.toArray(new Predicate[] {})))