Lets say I have an entity:
@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
}
I want a to build a query using the Criteria API that filters these users and shows a list of people and among other info from the entity - how many roles does a person have.
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Person> query = builder.createQuery(Person.class);
Root<Person> personRoot = query.from(Person.class);
// predicates here
However, this limits me to returning only a list of Person
entities. I can always add a @Transient
field to the entity, but this seems ugly since I might have many different queries and might end up with many such fields.
On the other hand - I cant use HQL
and write the query since I want complex filtering and I would have to deal with appending and removing things from the HQL
query.
My question, besides the one in the title of this post is this: how do I query the database using the Criteria API and return a non-entity (in case I want to filter the Person table but return only the number of roles, permissions, etc) and how do I do it for something very close to the actual entity (like the example with the role counter instead of the roles collection)?
UPDATE
Using Hibernate's projections I came up with this. But still don't know that to write in TODO
. Projections.count
doesn't work since it excpects some kind of grouping, and I don't seem to be able to find any examples in the Hibernate
documentation.
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");