JPA 条件 - 使用 where 子句获取

JPA Criteria - fetch with where clause

我有以下查询工作正常:

public ContractorContractor findContractorByName(String contractorName) {
   CriteriaBuilder builder = em.getCriteriaBuilder();
   CriteriaQuery<ContractorContractor> query = builder.createQuery(ContractorContractor.class);
   Root<ContractorContractor> root = query.from(ContractorContractor.class);
   query.select(root).distinct(true);

   Predicate namePredicate = builder.like(root.get(ContractorContractor_.name), contractorName);
   query.where(builder.and(namePredicate));

   return em.createQuery(query).getSingleResult();
}

以上查询按名称给出了单一承包商或抛出异常。 现在我想做同样的事情但获得更多关于承包商的信息(将提取添加到承包商的另一个 child)但是通过以下查询我没有得到结果(org.springframework.dao.EmptyResultDataAccessException:没有找到查询的结果是扔)。使用 fetch 查询:

public ContractorContractor findContractorByName(String contractorName) {
   CriteriaBuilder builder = em.getCriteriaBuilder();
   CriteriaQuery<ContractorContractor> query = builder.createQuery(ContractorContractor.class);
   Root<ContractorContractor> root = query.from(ContractorContractor.class);
   root.fetch(ContractorContractor_.countries);
   query.select(root).distinct(true);

   Predicate namePredicate = builder.like(root.get(ContractorContractor_.name), contractorName);
   query.where(builder.and(namePredicate));

   return em.createQuery(query).getSingleResult();
}

谁能告诉我我在上面的查询中做错了什么以及为什么?

看来您通过添加 inner fetch join 并添加以下语句不小心限制了查询域:

root.fetch(ContractorContractor_.countries);

根据 JPA 2.1,JSR 338,第 6.5.4 节

[...] A fetch join has the same join semantics as the corresponding inner or outer join [...]

因此将隐式 inner fetch join (JoinType.INNER) 更改为 (outer) left fetch join 应该可以解决您的问题问题:

root.fetch(ContractorContractor_.countries, JoinType.LEFT);

这种副作用可能看起来有点出乎意料,这可能就是规范作者添加以下注释的原因(尽管在标准连接的上下文中,第 4.4.7 节):

Application developers should use caution in defining identification variables because the domain of the query can depend on whether there are any values of the declared type.