Hibernate Query Language (HQL) is an object-oriented query language used to query Hibernate-managed entities.
Key idea:
HQL works with Java classes and fields, not database tables and columns.
Hibernate translates HQL into database-specific SQL internally.
HQL was designed to solve problems of raw SQL in ORM-based applications.
- Tightly coupled to table names
- Database-specific syntax
- Manual mapping of result sets to objects
- Database independent
- Uses entity names and properties
- Automatic object mapping
- Integrates with Hibernate caching
- Cleaner and maintainable
| Aspect | SQL | HQL |
|---|---|---|
| Works on | Tables & columns | Entities & fields |
| Result | Rows | Objects |
| DB Dependency | Yes | No |
| Object Mapping | Manual | Automatic |
| Case Sensitivity | Column/table dependent | Entity/field sensitive |
SELECT * FROM student WHERE age > 20;FROM Student WHERE age > 20Student→ Entity class nameage→ Entity field
General format:
FROM EntityName [WHERE condition]or
SELECT alias FROM EntityName alias [WHERE condition]Query<Student> query = session.createQuery("FROM Student", Student.class);
List<Student> students = query.getResultList();Generated SQL internally:
SELECT * FROM student;Query<Student> query =
session.createQuery("FROM Student WHERE age > 20", Student.class);
List<Student> list = query.getResultList();Student s = session
.createQuery("FROM Student WHERE id = 1", Student.class)
.uniqueResult();Always use parameters to prevent SQL injection.
Query<Student> query =
session.createQuery("FROM Student WHERE age > :age", Student.class);
query.setParameter("age", 20);
List<Student> list = query.list();Query<Student> query =
session.createQuery("FROM Student WHERE age > ?1", Student.class);
query.setParameter(1, 20);Named parameters are preferred for readability.
HQL supports selecting specific fields.
Query<String> query =
session.createQuery("SELECT name FROM Student", String.class);
List<String> names = query.list();Query<Object[]> query =
session.createQuery("SELECT name, age FROM Student");
List<Object[]> list = query.list();
for (Object[] row : list) {
String name = (String) row[0];
int age = (int) row[1];
}(DTO = Data Transfer Object)
Query<StudentDTO> query =
session.createQuery(
"SELECT new com.dto.StudentDTO(name, age) FROM Student",
StudentDTO.class
);This avoids Object[] handling and improves clarity.
FROM Student ORDER BY age DESCMultiple fields:
FROM Student ORDER BY age DESC, name ASCSELECT department, COUNT(*) FROM Student GROUP BY departmentSELECT department, COUNT(*)
FROM Student
GROUP BY department
HAVING COUNT(*) > 5Hibernate supports SQL-like aggregate functions:
| Function | Usage |
|---|---|
COUNT() |
Number of records |
SUM() |
Sum of values |
AVG() |
Average |
MIN() |
Minimum |
MAX() |
Maximum |
Long count =
session.createQuery("SELECT COUNT(*) FROM Student", Long.class)
.uniqueResult();Bulk operations bypass Hibernate session cache.
Transaction tx = session.beginTransaction();
Query query =
session.createQuery("UPDATE Student SET age = 25 WHERE id = 1");
int rows = query.executeUpdate();
tx.commit();Transaction tx = session.beginTransaction();
Query query =
session.createQuery("DELETE FROM Student WHERE age < 18");
int rows = query.executeUpdate();
tx.commit();HQL supports object-oriented joins.
FROM Student s JOIN s.department dFROM Student s LEFT JOIN s.department dSELECT d FROM Department d JOIN FETCH d.studentsPurpose:
- Fetch parent + child in single query
- Avoid N+1 problem
Hibernate provides built-in pagination support.
Query<Student> query =
session.createQuery("FROM Student", Student.class);
query.setFirstResult(0); // offset
query.setMaxResults(10); // limit
List<Student> list = query.list();Equivalent SQL:
LIMIT 10 OFFSET 0Query query = session.createQuery("FROM Student");
query.setCacheable(true);- Requires Second-Level Cache
- Stores query result IDs
- Entities fetched from cache if cacheable
| Feature | HQL | Criteria API | Native SQL |
|---|---|---|---|
| Type | String-based | Type-safe | SQL |
| DB Independent | Yes | Yes | No |
| Readability | High | Medium | High |
| Compile-time Safety | No | Yes | No |
| Use Case | Most common | Dynamic queries | Complex DB-specific queries |
Session session = HibernateUtil.getSessionFactory().openSession();
Query<Student> query =
session.createQuery(
"FROM Student WHERE age > :age ORDER BY name",
Student.class
);
query.setParameter("age", 20);
List<Student> students = query.getResultList();
session.close();An object-oriented query language that works on Hibernate entities, not tables.
HQL uses entity names and fields; SQL uses tables and columns.
Yes. Hibernate converts HQL into DB-specific SQL.
Yes, object-oriented joins using associations.
Yes, using bulk queries (executeUpdate()).
A join that loads related entities in the same query to avoid N+1 problem.
Yes, via setFirstResult() and setMaxResults().
HQL for ORM-based queries; SQL for DB-specific optimizations.
-
HQL is Hibernate’s object-oriented alternative to SQL
-
Uses entity names and fields, not tables
-
Automatically maps results to objects
-
Supports joins, aggregation, pagination, caching
-
Essential for real-world Hibernate applications