1. Знайомство з HQL

Раніше ми познайомилися з Hibernate, а тепер я познайомлю тебе з HQL, він же — Hibernate Query Language. Фактично, це SQL перероблений під написання запитів в Hibernate. Він має кілька ключових відмінностей.

  1. Використання імені класу замість імені таблиці.
  2. Використання імені поля класу замість імені колонки таблиці.
  3. Необов'язкове використання select.

Давай попросимо Hibernate повернути нам усіх користувачів, які є у нього в базі. Ось як виглядатиме цей запит:


from
        

Це все. Для порівняння наведемо аналогічний запит на SQL:


select * from user
        

Тут User — це ім'я класу, а user — це ім'я таблиці.

Цілком Java код виглядатиме ось так:


public List<User> getAllUsers() {
    try (Session session = sessionFactory.openSession()) {
            return session.createQuery("from User", User.class).list();
    }
}

В іншому HQL дуже схожий на SQL — у ньому теж є оператори:

  • WHERE
  • ORDER BY
  • GROUP BY
  • HAVING

2. Приклад роботи з HQL

Можливо, попередній приклад трохи збиває з пантелику через однакові назви таблиць і полів. Давай придумаємо спеціальний приклад, де з цим було б легше.

Скажімо, в нас є таблиця user_data, яка містить такі поля:

  • id INT
  • user_name VARCHAR(100)
  • user_level INT
  • user_created DATE

Ми створимо Java-клас, який замапимо на цю таблицю:


@Entity
@Table(name="user_data")
class User {
   @Id
   @GeneratedValue
   public Integer id;
 
   @Column(name="user_name")
   public String name;
 
   @Column(name="user_level")
   public Integer level;
 
   @Column(name="user_created")
   public Date created;
}

Тепер напишемо кілька прикладів:

HQL SQL
from User select * from user_data
from User where id=3 select * from user_data where id=3
from User where level in (10,20,30) select * from user_data where user_level IN (10, 20, 30)
from User order by created asc select * from user_data order by user_created asc
from User where name like 'тест' select * from user_data where user_name like 'тест'

Запити дуже схожі, і читати HQL-запити, коли ти знайомий з іменами класів та їх полів так само легко, як читати SQL-запити. Писати, можливо, трохи складніше, але знову ж таки, на HQL рідко пишуть дуже складні запити.

3. Використання select

У HQL можна використовувати select, коли тип даних результату не збігається з типом, зазначеним у from.

Наприклад, ми хочемо отримати імена всіх користувачів, які є в нашій таблиці user_data, тоді потрібно написати такий запит:


select name from
        

Також якщо серед імен є дублікати, можна скористатися оператором DISTINCT:


select distinct name from
        

Аліаси працюють так само, як і в SQL:


select distinct u.name from User u where u.created > '2020-01-01'

        

Ну і повністю у Java-коді цей запит буде виглядати так:


public List<String> getUserNames() {
    try (Session session = sessionFactory.openSession()) {
            String hql = "select distinct u.name from User u where u.created > '2020-01-01'";
            Query<String> query = session.createQuery(hql , String.class);
            return query.list();
    }
}

Зверни увагу: запит має повернути список імен. Імена мають тип String, тому і тип функції, і тип параметра класу Query мають тип String.