JPQL
About
JPQL is the object-oriented query language defined by the Java Persistence API (JPA). It’s similar in syntax to SQL but operates on the entity object model rather than directly on database tables.
SQL works on tables, rows, columns.
JPQL works on entities, fields, relationships.
Some of the Features of JPQL
Queries entities and their relationships using object-based syntax.
Supports CRUD operations using HQL-like statements.
Abstracts underlying SQL and RDBMS-specific queries.
Enables navigation across entity relationships like
@OneToMany
,@ManyToOne
.Strongly integrated with JPA EntityManager.
JPQL Query Types
1. Basic SELECT
Fetch entities or specific fields from a table (entity).
TypedQuery<Employee> query = em.createQuery(
"SELECT e FROM Employee e", Employee.class);
List<Employee> result = query.getResultList();
Fetch all employees from the database.
2. SELECT with WHERE Clause
TypedQuery<Employee> query = em.createQuery(
"SELECT e FROM Employee e WHERE e.department = :dept", Employee.class);
query.setParameter("dept", "Finance");
Find all employees in the Finance department.
3. Selecting Specific Fields (Projection)
TypedQuery<String> query = em.createQuery(
"SELECT e.name FROM Employee e", String.class);
Fetch just the names of all employees.
Or multiple fields:
TypedQuery<Object[]> query = em.createQuery(
"SELECT e.name, e.salary FROM Employee e", Object[].class);
4. Using Aggregate Functions
Query query = em.createQuery(
"SELECT AVG(e.salary) FROM Employee e");
Double averageSalary = (Double) query.getSingleResult();
Get average salary across all employees.
5. GROUP BY and HAVING
Query query = em.createQuery(
"SELECT e.department, COUNT(e) FROM Employee e GROUP BY e.department HAVING COUNT(e) > 5");
Find departments with more than 5 employees.
6. JOINs (Entity Relationships)
JPQL handles joins using entity fields, not tables.
TypedQuery<Project> query = em.createQuery(
"SELECT p FROM Project p JOIN p.employees e WHERE e.name = :name", Project.class);
query.setParameter("name", "John Doe");
Get projects where John Doe is assigned.
7. ORDER BY Clause
TypedQuery<Employee> query = em.createQuery(
"SELECT e FROM Employee e ORDER BY e.salary DESC", Employee.class);
List employees sorted by salary (highest first).
8. IN Clause
List<String> departments = List.of("IT", "HR");
TypedQuery<Employee> query = em.createQuery(
"SELECT e FROM Employee e WHERE e.department IN :departments", Employee.class);
query.setParameter("departments", departments);
Get employees from IT or HR.
9. LIKE Clause (Pattern Matching)
TypedQuery<Employee> query = em.createQuery(
"SELECT e FROM Employee e WHERE e.name LIKE :name", Employee.class);
query.setParameter("name", "A%");
Find employees whose name starts with 'A'.
10. Subqueries
TypedQuery<Employee> query = em.createQuery(
"SELECT e FROM Employee e WHERE e.salary > (SELECT AVG(e2.salary) FROM Employee e2)", Employee.class);
Get employees earning above the average salary.
11. UPDATE and DELETE
JPQL supports
UPDATE
andDELETE
, but not INSERT.
UPDATE
Query query = em.createQuery(
"UPDATE Employee e SET e.salary = e.salary * 1.1 WHERE e.department = :dept");
query.setParameter("dept", "IT");
int updated = query.executeUpdate();
Give 10% raise to IT department.
DELETE
Query query = em.createQuery(
"DELETE FROM Employee e WHERE e.status = :status");
query.setParameter("status", "INACTIVE");
int deleted = query.executeUpdate();
Remove all inactive employees.
12. Constructor Expressions (DTO Projection)
TypedQuery<EmployeeDTO> query = em.createQuery(
"SELECT new com.example.EmployeeDTO(e.name, e.salary) FROM Employee e", EmployeeDTO.class);
Return results in a custom DTO.
Limitations of JPQL
No support for INSERT.
Complex SQL (window functions, full joins, recursive CTEs) not supported.
Limited database-specific syntax (must switch to native queries).
Last updated
Was this helpful?