I\'m studying JPA criteria api and my database contains Employee table. I am trying to find all the employees who are paid second highest salary. I was able to write JPQL su
After some more trial and error, I could write the query to select employees with second maximum salary. I would like to suggest that you should write a JPQL query first and write the criteria api accordingly. This is what I analyzed from JPQL.
SELECT e FROM Employee e
WHERE e.salary = (SELECT MAX(emp.salary) FROM Employee emp
WHERE emp.salary < (SELECT MAX(employee.salary) FROM Employee employee) )
Now we can see that
WHERE emp.salary = (SELECT MAX(emp.salary) FROM Employee emp)
Now let us convert this query in criteria api.
First write CriteriaQuery that corresponds to outermost query i.e. SELECT e FROM Employee e WHERE e.salary =
CriteriaQuery c1 = cb.createQuery(Employee.class);
Root e3 = c1.from(Employee.class);
c1.select(e3);
Let us leave the WHERE e.salary =
for now and go for the subquery
Now this should have a subquery that selects the maximum salary of employees i.e. SELECT MAX(emp.salary) FROM Employee emp
WHERE emp.salary <
again let us leave the WHERE emp.salary <
for now.
Subquery sq1 = c1.subquery(Long.class);
Root e4 = sq1.from(Employee.class);
sq1.select(cb.max(e4. get("salary")));
repeating this for subquery of above subquery,
Subquery sq2 = sq1.subquery(Long.class);
Root e5 = sq2.from(Employee.class);
sq2.select(cb.max(e5. get("salary")));
Now we have written subqueries but WHERE
conditions need to be applied yet. So now the where condition in criteria api corresponding to WHERE emp.salary < (SELECT MAX(employee.salary) FROM Employee employee)
will be as below.
sq1.where(cb.lessThan(e4. get("salary"), sq2));
Similarly, WHERE condition corresponding to WHERE e.salary = (SELECT MAX(emp.salary) FROM Employee emp
will be as below.
c1.where(cb.equal(e3. get("salary"), sq1));
So the complete query which gives the employees with second highest salary can be written in criteria api as below.
CriteriaQuery c1 = cb.createQuery(Employee.class);
Root e3 = c1.from(Employee.class);
c1.select(e3);
Subquery sq1 = c1.subquery(Long.class);
Root e4 = sq1.from(Employee.class);
sq1.select(cb.max(e4. get("salary")));
Subquery sq2 = sq1.subquery(Long.class);
Root e5 = sq2.from(Employee.class);
sq2.select(cb.max(e5. get("salary")));
sq1.where(cb.lessThan(e4. get("salary"), sq2));
c1.where(cb.equal(e3. get("salary"), sq1));
employees = em.createQuery(c1).getResultList();
for (Employee employee : employees) {
System.out.println(employee.getName() + " " + employee.getSalary());
}