使用 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[] {})))
我在 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[] {})))