简体   繁体   中英

JPA/Hibernate SELECT all parent fields with Child count in Single Query

I am using JPA 2.0, with Hibernate 1.0.1.Final.

I want all Parent table fields with no of children in single query.

In Other word, I want to translate from SQL into CriteriaAPI of JPA/Hibernate.

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

I have following JPA Entities.

@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;
}

My Current Criteria Query is like this :

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

Now the Problem is, It fires multiple Queries to the database. 1) One query to retrieve groupId and no of count of users 2) N Queries to retrieve group info for each group.

I want only one Query to retrieve GroupInfo and no of count of the users as shown in Above SQL Query.

Please give me good suggestion.

Implement Using the bellow Code.

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

This code will work. for child count.

you must have the constructor of the class KernelGroupDto(Long id, Long childCount)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM