获取集合计数而不是JPA Criteria API中的集合?

时间:2013-11-18 21:33:40

标签: java hibernate jpa hql criteria

假设我有一个实体:

@Entity
public class Person {

    @Id
    @GeneratedValue
    private Long id;

    @ManyToMany(fetch = FetchType.LAZY)
    private List<Role> roles;

    @ManyToMany(fetch = FetchType.LAZY)
    private List<Permission> permissions;
    // etc
    // other fields here
}

我希望使用Criteria API构建一个查询,过滤这些用户并显示人员列表以及实体中的其他信息 - 一个人拥有多少个角色。

CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Person> query = builder.createQuery(Person.class);
Root<Person> personRoot = query.from(Person.class);
// predicates here

但是,这限制了我只返回Person个实体的列表。我总是可以在实体中添加一个@Transient字段,但这看起来很难看,因为我可能有很多不同的查询,最终可能会有很多这样的字段。

另一方面 - 我无法使用HQL并编写查询,因为我想要复杂的过滤,我将不得不处理从HQL查询中追加和删除内容。

我的问题,除了这篇文章标题中的一个是这样的:我如何使用Criteria API查询数据库并返回一个非实体(如果我想过滤Person表但只返回数量角色,权限等)以及如何为非常接近实际实体的事情做这件事(比如角色计数器而不是角色集合的例子)?

更新 使用Hibernate的预测我想出了这个。但仍然不知道写在TODOProjections.count不起作用,因为它会考虑某种分组,我似乎无法在Hibernate文档中找到任何示例。

Criteria cr = session.createCriteria(Person.class);

if (id != null) {
    cr.add(Restrictions.eq("id", id));
}

ProjectionList projectionList = Projections.projectionList();
projectionList.add(Projections.property("id"), "id");
projectionList.add(TODO, "rolesCount");

2 个答案:

答案 0 :(得分:0)

  

我如何做一些非常接近实际实体的事情(比如   带有角色计数器的示例而不是角色集合

您可以通过各种方式为User实体创建这些值属性,例如使用Hibernate @Forumula属性。这将在Entity load上发出一个内联子查询,以便在不触及集合的情况下获取计数。

@Formula("select count(*) from roles where user_id = ?")
private int numberOfRoles;

另一个(JPA兼容)选项是通过在数据库级别创建一个视图并将其映射到您的用户来处理这些计算字段:

e.g。

@OneToOne
private UserData userData; //entity mapped to your view (works just like a table)

....

public int getNumberOfRoles(){
   return userData.getRoleCOunt();

使用@SecondaryTable加入此用户数据。

答案 1 :(得分:0)

CriteriaQuery<Long> query = entityManager.getCriteriaBuilder().get().createQuery(Long.class);
query.select(builder.get().countDistinct(root));

适合我:)