JPA Criteria - 使用where子句获取

时间:2016-06-10 11:43:49

标签: java hibernate jpa criteria-api

我有以下查询正常工作:

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();
}

以上查询按名称给我单一承包商或抛出异常。 现在我想做同样的事情,但获得有关承包商的更多信息(将fetch添加到承包商的另一个孩子)但是使用以下查询我得不到结果(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();
}

有人可以告诉我我做错了什么以及为什么在上面的查询中?

1 个答案:

答案 0 :(得分:2)

您似乎通过添加内部提取连接并添加以下语句而意外限制了查询的域:

root.fetch(ContractorContractor_.countries);

根据JPA 2.1,JSR 338,第6.5.4节

  

[...]获取连接具有相同的连接语义作为相应的内部或外部连接[...]

因此,将隐式内部提取连接JoinType.INNER)更改为(外部)左提取连接可以解决您的问题:

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

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

  

应用程序开发人员在定义标识变量时应谨慎,因为查询的域可能取决于声明类型是否有任何值