Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# JPQL vs HQL — Различия
Определение
HQL (Hibernate Query Language) — это язык запросов, специфичный для Hibernate. Он был создан в 2003 году как часть Hibernate ORM и работает только с этим фреймворком.
JPQL (Java Persistence Query Language) — это стандартный язык запросов, определённый в спецификации JPA (Java Persistence API). Он работает с любым JPA-провайдером (Hibernate, EclipseLink, OpenJPA).
Основные различия
1. Стандартизация
- HQL — proprietary (проприетарный язык Hibernate)
- JPQL — стандарт Java, работает везде
// HQL (только в Hibernate)
String hql = "FROM User u WHERE u.email = :email";
Query<User> query = session.createQuery(hql, User.class);
// JPQL (везде, где JPA)
@Query("SELECT u FROM User u WHERE u.email = ?1")
User findByEmail(String email);
2. Обязательность SELECT
- HQL позволяет опускать SELECT:
FROM User u - JPQL требует явный SELECT:
SELECT u FROM User u
// HQL
String hql = "FROM User u WHERE u.active = true"; // ✅ работает
String hql2 = "SELECT u FROM User u WHERE u.active = true"; // ✅ тоже работает
// JPQL
@Query("SELECT u FROM User u WHERE u.active = true") // ✅ работает
@Query("FROM User u WHERE u.active = true") // ❌ ошибка
3. Портативность
- HQL привязан к Hibernate (vendor lock-in)
- JPQL переносим между разными JPA-провайдерами
// JPQL — можно перейти с Hibernate на EclipseLink
// HQL — только Hibernate, миграция требует переписания запросов
Синтаксис — различия
| Аспект | HQL | JPQL |
|---|---|---|
| SELECT | Опционален | Обязателен |
| Синтаксис | FROM User u | SELECT u FROM User u |
| Провайдер | Только Hibernate | Любой JPA провайдер |
| Функции | Много Hibernate-специфичных | Базовый стандартный набор |
| Тип-безопасность | Нет (String запросы) | Да (Criteria API) |
Примеры
HQL (legacy)
public class UserDAO {
public User findByEmail(String email) {
String hql = "FROM User u WHERE u.email = :email";
return session.createQuery(hql, User.class)
.setParameter("email", email)
.uniqueResult();
}
public List<User> findAdults() {
String hql = "FROM User u WHERE u.age >= 18 ORDER BY u.name";
return session.createQuery(hql, User.class).list();
}
}
JPQL (modern)
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
@Query("SELECT u FROM User u WHERE u.email = :email")
User findByEmail(@Param("email") String email);
@Query("SELECT u FROM User u WHERE u.age >= 18 ORDER BY u.name")
List<User> findAdults();
}
Сравнение
| Характеристика | HQL | JPQL |
|---|---|---|
| Стандарт | ❌ Proprietary | ✅ JPA Standard |
| Переносимость | ❌ Только Hibernate | ✅ Все JPA провайдеры |
| SELECT обязателен | ❌ Нет | ✅ Да |
| Тип-безопасность | ❌ String запросы | ✅ Criteria API |
| Spring Data JPA | ⚠️ Работает | ✅ Встроена |
| Рекомендация | ❌ Legacy | ✅ Используй это |
Criteria API — типобезопасная альтернатива
// Criteria API — лучшая альтернатива для динамических запросов
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<User> query = cb.createQuery(User.class);
Root<User> user = query.from(User.class);
query.where(cb.and(
cb.equal(user.get("active"), true),
cb.ge(user.get("age"), 18)
));
return em.createQuery(query).getResultList();
Когда использовать
Используй JPQL если:
- ✅ Новый проект
- ✅ Используешь Spring Data JPA
- ✅ Нужна портативность
- ✅ Простые-средние запросы
Используй Criteria API если:
- ✅ Динамические запросы
- ✅ Нужна полная тип-безопасность
- ✅ Сложные условия
НЕ используй HQL если:
- ❌ Это новый проект
- ❌ Хочешь избежать vendor lock-in
- ❌ Нужна портативность
Вывод
HQL — это legacy технология, привязанная к Hibernate. JPQL — это стандарт Java, поддерживаемый всеми JPA-провайдерами. В новых проектах используй JPQL или Criteria API. Если обновляешь старый код на HQL, постепенно переводи на JPQL.