JPA / Hibernate在单个查询中选择具有子计数的所有父字段

时间:2016-04-21 10:42:49

标签: java hibernate jpa

我正在使用JPA 2.0,使用Hibernate 1.0.1.Final。

我想在单个查询中没有子节点的所有父表字段。

换句话说,我想从SQL转换为JPA / Hibernate的CriteriaAPI。

select kgroup.*, count(userGroup.uid) 
from kernelGroup kgroup 
 left join kernelUserGroup userGroup on (kgroup.groupId = userGroup.groupId) 
group by kgroup.groupId

我有以下JPA实体。

@Entity
@Table(name="kernel_group")
public class KernelGroup implements Serializable {

  @Id
  private int groupId;

  private boolean autoGroup;

  private String groupName;

  @OneToMany
  private Set<KernelUserGroup> kernelUserGroups;

  private long jpaVersion; 
}


@Entity
@Table(name="kernel_usergroup")
public class KernelUserGroup implements Serializable {

  @EmbeddedId
  private KernelUserGroupPK id;

  private long jpaVersion;

  @ManyToOne
  private KernelGroup kernelGroup;

  @ManyToOne
  private KernelUser kernelUser;
}

@Embeddable
public class KernelUserGroupPK implements Serializable {
  private String uid;
  private int groupId;
}

我的当前标准查询是这样的:

CriteriaBuilder cb = em.getCriteriaBuilder();  
CriteriaQuery<KernelGroupDto> cQuery = cb.createQuery(KernelGroupDto.class);  
Root<KernelGroup> root = cQuery.from(KernelGroup.class);  

Join<KernelGroup, KernelUserGroup> userGroupsJoin = root.join(KernelGroup_.kernelUserGroups, JoinType.LEFT);    

cQuery.select(cb.construct(KernelGroupDto.class, root, cb.count(userGroupsJoin.get(KernelUserGroup_.id).get(KernelUserGroupPK_.uid))));

cQuery.groupBy(root.get(KernelGroup_.groupId));    

em.createQuery(cQuery).getResultList();    

现在的问题是,它会向数据库发出多个查询。 1)一个查询检索groupId而没有用户数 2)N个查询,以检索每个组的组信息。

我只想要一个Query来检索GroupInfo,而不需要用户数,如上面的SQL Query所示。

请给我一个好的建议。

1 个答案:

答案 0 :(得分:0)

使用以下代码实现。

CriteriaBuilder cb = em.getCriteriaBuilder();  
CriteriaQuery<KernelGroupDto> cQuery = cb.createQuery(KernelGroupDto.class);  
Root<KernelGroup> root = cQuery.from(KernelGroup.class);  

Join<KernelGroup, KernelUserGroup> userGroupsJoin = 
root.join(KernelGroup_.kernelUserGroups, JoinType.LEFT);    

cQuery.select(cb.construct(KernelGroupDto.class, root. 
<Long>get("id"),cb.count(userGroupsJoin)));
cQuery .groupBy( root.<Long>get("id") );

cQuery.groupBy(root.get(KernelGroup_.groupId));    

em.createQuery(cQuery).getResultList(); 

此代码将起作用。来计算孩子数。

您必须具有类KernelGroupDto(Long id,Long childCount)的构造函数