← Назад к вопросам

В чем разница между JPQL и HQL?

2.0 Middle🔥 141 комментариев
#ORM и Hibernate

Комментарии (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, миграция требует переписания запросов

Синтаксис — различия

АспектHQLJPQL
SELECTОпционаленОбязателен
СинтаксисFROM User uSELECT 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();
}

Сравнение

ХарактеристикаHQLJPQL
Стандарт❌ 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.

В чем разница между JPQL и HQL? | PrepBro