1. Зв'язуємо Hibernate та бази даних

Ми навчилися підключати Hibernate до нашої програми за допомогою Maven, а також мапити таблиці на класи за допомогою анотацій. І тепер виникає наступне питання: а як нам прочитати об'єкти з бази даних чи зберегти їх туди?

Не так швидко. Насамперед потрібно розібратися ще з трьома речами:

  • Конфігурування підключення до бази даних
  • Налаштування Hibernate
  • Робота з EntityManager

Hibernate повністю приховує від твоєї програми роботу з базою даних, але щоб не було жодних ексцесів, його потрібно правильно налаштувати. Пропустити цей етап не можна — як інакше Hibernate дізнається, до якої бази даних йому зберігати об'єкти?

Конфігурувати Hibernate та вказати для нього інформацію про базу даних можна трьома способами

  • Використовувати Properties-файл
  • Використовувати файл hibernate.cfg.xml
  • Використовувати методи біна Configuration

І хоча мені найбільше подобається останній, ти точно зіштовхуватимешся з усіма трьома, отже ми всі три тут і розберемо.

2. Авторизація у базі даних

Почнемо з найважливішого — підключення бази даних. Для цього тобі потрібно буде вказати дані, щоб Hibernate міг авторизуватись у потрібній базі даних.

Properties File Configuration
hibernate.properties

hibernate.dialect= org.hibernate.dialect.Oracle9Dialect
hibernate.connection.driver_class=oracle.jdbc.driver.OracleDriver
hibernate.connection.url= jdbc:oracle:thin:@localhost:1521:supershop
hibernate.connection.username=root
hibernate.connection.password=secret
hibernate.show_sql=true
hibernate.hbm2ddl=update

Ці ж установки можна зробити у вигляді xml-файлу:

XML Based Configuration
hibernate.cfg.xml

<hibernate-configuration>
<session-factory>
        
    <property name="dialect">org.hibernate.dialect.Oracle9Dialect</property>
    <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
    <property name="connection.url">jdbc:oracle:thin:@localhost:1521:supershop</property>
    <property name="connection.username">root</property>
    <property name="connection.password">secret</property>
    <property name="hibernate.show_sql ">true</property>
    <property name="hbm2ddl.auto">update</property> 
     
</session-factory>
</hibernate-configuration>

В обох прикладах ми бачимо ті самі налаштування з одними й тими самими значеннями. Просто перший приклад представляє їх у вигляді properties-файлу, а другий — у вигляді xml-файлу.

Ці параметри поділяються на три групи:

  1. Вказуємо тип СУБД
    • Вказуємо діалект (тип СУБД), наприклад, Oracle 9.0
    • Вказуємо ім'я JDBC-драйвера для роботи з даною СУБД
  2. Вказуємо дані для авторизації в базі
    • url бази
    • username
    • password
  3. Конфігуруємо двигун Hibernate
    • hibernate.show_sql — Hibernate дублюватиме в консолі всі запити, які виконує
    • hbm2ddl.auto — Hibernate змінить структуру бази даних, якщо треба

Є ще третій спосіб встановлення конфігурації через біни. Зазвичай він використовується в парі зі Spring, тому ми розглянемо його, коли вивчатимемо SpringFramework.

3. Отримуємо SessionFactory

Наступний етап — це отримати об'єкт SessionFactory. Є кілька способів зробити це:

Спосіб перший — використовується файл hibernate.properties.

Для цього потрібно просто написати такий код:


SessionFactory sessionFactory = new Configuration().buildSessionFactory();

Якщо файл hibernate.properties не знайдеться в src/main/resources, то кинеться виняток.

Спосіб другий — конфігурація за допомогою hibernate.cfg.xml.


SessionFactory sessionFactory = new Configuration().configure(). buildSessionFactory();

Якщо ти напишеш такий код, як джерело налаштувань буде використано файл hibernate.cfg.xml. Якщо такий файл не буде знайдено, метод buildSessionFactory() кине виняток.

Спосіб третій — вказуємо файл із конфігурацією вручну.

Іноді в процесі розробки виникає необхідність переключитися на тестову базу або змінити інші налаштування для роботи з базою, для цього можна вказати файл конфігурації вручну:


SessionFactory sessionFactory = new Configuration().configure("hibernate-dev.cfg.xml").buildSessionFactory ();

Спосіб четвертий — використовується кастомний файл hibernate.properties:


ClassLoader classLoader = Thread.currentThread().getClassLoader();
 
Properties properties = new Properties();
properties.load(classLoader.getResourceAsStream("hibernate-dev.properties"));
 
SessionFactory sessionFactory = new Configuration()
            .addProperties(properties)
            .buildSessionFactory();

І нарешті можна просто зашити всі потрібні параметри прямо до коду:


Properties properties = new Properties();
properties.put(Environment.DRIVER, "com.mysql.jdbc.Driver");
properties.put(Environment.URL, "jdbc:mysql://localhost:3306/supershop") ;
properties.put(Environment.USER, "root");
properties.put(Environment.PASS, "password");
 
SessionFactory sessionFactory = new Configuration()
            .setProperties(properties)
            .buildSessionFactory();

4. Вказуємо, де шукати Entity-класи

Але це ще не все. Коли ми конфігуруємо об'єкт SessionFactory в Hibernate, цей SessionFactory перевіряє, що в базі даних існують всі необхідні таблиці з колонками необхідних типів.

І щоб SessionFactory міг це зробити, йому потрібно передати список entity-класів, які йому треба порівняти з базою даних.

Передати список entity-класів можна трьома способами:

Спосіб перший. У hibernate.cfg.xml додати рядок типу:


<mapping class="повне ім'я класу" />
        

Приклад:


    <mapping class="com.javarush.data.User" />
    <mapping class="com.javarush.data.Employee" />
    <mapping class="com.javarush.data.Task" />

Спосіб другий. Викликати в об'єкті Configuration метод addAnnotatedClass(). Приклад:


SessionFactory sessionFactory = new Configuration()
   .configure()
   .addAnnotatedClass(com.javarush.data.User.class)
   .buildSessionFactory();

Якщо класів багато, можна додавати їх цілими пакетами:


SessionFactory sessionFactory = new Configuration()
   .configure()
   .addPackage("com.javarush.data")
   .buildSessionFactory();

5. Фінальний приклад

Після того, як ми навчилися конфігурувати об'єкт SessionFactory, давай напишемо код, який його використовуватиме.

Він складатиметься з трьох методів:

  1. Конфігуруємо Hibernate
  2. Метод, який отримує всіх співробітників із бази
  3. Метод, який зберігає нового співробітника до бази

Шаблон цього коду буде виглядати приблизно так:


class EmployeeManager {
    private SessionFactory sessionFactory;
 
    public void class init() {
    this.sessionFactory = new Configuration()
        .configure()
        .buildSessionFactory();
   }
 
   public List<Employee> getAllEmployes() {
         try (Session session = sessionFactory.openSession()) {
  Query<Employee> query = session.createQuery("from Employee", Employee.class);
    return query.list();
         }
   }
 
   public void addEmployee(Employee employee ) {
     try (Session session = sessionFactory.openSession()) {
            Transaction transaction = session.beginTransaction();
       session.save(employee);
            transaction.commit();
     }
   }
}

Перш ніж виконати запит до бази, потрібно створити окрему сесію. Якщо запити пов'язані, вони можуть виконуватися в одній сесії. Якщо запити не пов'язані (і між ними може пройти кілька хвилин), то для них потрібно робити власні сесії.

Якщо ти хочеш прочитати дані з бази або виконати складний запит, потрібно спочатку створити об'єкт Query, і за його допомогою виконати свій запит.

Також кожен запит до бази виконується у власній транзакції. Її потрібно відкрити, виконати потрібні операції, а потім закрити (закоммітити).

У наступних лекціях ми детальніше розберемо, як це все працює.