I currently have a Spring Boot application with Hibernate mapped entities. One of them is say an Employee
, and I'd like to get all the employee usernames by department.
Something like the SQL:
SELECT username FROM employee WHERE departmentId=1 AND active=true;
Employee class:
@Entity
public class Employee extends BaseEntity implements Serializable {
private int id;
private String name;
private String username;
private String building;
private Integer departmentId;
private Boolean active;
... other stuff about them ...
... annotated getters and setters ...
}
I (believe I) can get all the Employees of department with something like:
public List<Employee> employeesInDepartment(Integer departmentId) {
Session session = getSession();
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Employee> criteriaQuery = builder.createQuery(Employee.class);
Root<Employee> root = criteriaQuery.from(Employee.class);
criteriaQuery.where(builder.and(
builder.equal(root.get("departmentId"), departmentId),
builder.equal(root.get("active"), true)))
.orderBy(builder.desc(root.get("timeCreated")))
.select(root);
return session.createQuery(criteriaQuery).list();
}
But say I want only a Set
of their usernames or buildings they're in, then I don't need to fill in the other 20+ fields about each employee and just need to get back the set of one field.
return session.createQuery(criteriaQuery).stream()
.map(Comment::getUsername).collect(Collectors.toSet());
However this wastes the transmission of the 20+ fields from the DB storage, and DB network back to the application service, and seems like the query as shown at the top would be the right one to represent in JPA's object notation. Yet, I'm not sure what to write instead; there wasn't an obvious Hibernate way to get a filtered down entity collection, so the JPA way seemed right, but I'm finding the documentation not as easy to grasp as I hoped. Am I looking at something like:
public Set<String> usernamesOfEmployeesInDepartment(Integer departmentId) {
Session session = getSession();
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Employee> criteriaQuery = builder.createQuery(Employee.class);
Root<Employee> root = criteriaQuery.from(Employee.class);
criteriaQuery.where(builder.and(
builder.equal(root.get("departmentId"), departmentId),
builder.equal(root.get("active"), true)))
.orderBy(builder.desc(root.get("timeCreated")))
.select(root).select(root.get("username"));
return new HashSet<>(session.createQuery(criteriaQuery).list());
}
That doesn't end up giving me the right type…
And if I wanted a distinct collection of a departments' employees' building locations, I need to throw in distinct
there somewhere too, but where?