Наверное трудно найти программиста, а тем более Java-программиста, который бы никогда не слышал о hibernate. Если вы инженер с опытом - статья может показаться вам глупой, бесполезной, но она ориентирована на тех, кто уже слышал о hibernate, но никогда не трогал его руками. Что могу сказать - пришло время потрогать.
На всякий случай, очень коротко о том, что это такое и зачем hibernate нужен. Итак, hibernate - это библиотека для Java, которая позволяет работать с таблицами БД, как обычными Java-обьектами. То есть не нужно писать SQL-запросы - hibernate все сделает за вас. Кому такого описания мало - милости прошу на официальный https://hibernate.org/. Там вам представится возможность убить пару недель свободного времени. В большинстве случаев официальная документация становится помощником только тогда, когда ты знаешь, что ты хочешь спросить. Эта статья скорее quickstart.
Основная проблема большинства фреймворков, и основная причина почему хочется постоянно отложить на потом их изучение - это некий набор действий, который надо выполнить ДО того, как будет написана первая строчка кода, реализующего логику приложения. Иногда достаточно просто подключить в pom.xml какую-нибудь зависимость, а иногда прямо надо серьезно заморочиться. Увы, с hibernate такая же ситуация.
Что нам потребуется (в скобочках я буду указывать версии):
JDK
(java version "21.0.2" 2024-01-16 LTS)
IDE (Idea 2023.1 Community Edition)
СУБД (PostgresSQL 16)
GUI для DB (pgAdmin4)
Предполагается, что все это счастье установлено на локальном хосте, настроено и проверено. В принципе СУБД может быть установлена, где угодно, но тогда заранее надо проверить, что связь с нею есть, и права у вашего пользователя на конкретную базу в наличии.
Создаем проект
Будем работать с проектом на maven, который идея создаст по умолчанию.

После того как дефолтовый проект создан, идем в папочку ˜Sources/hibernate_quick_start/src/main/resources, где создаем файл конфигурации hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection properties -->
<property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
<property name="hibernate.connection.url">jdbc:postgresql://localhost:5433/examples</property>
<property name="hibernate.connection.username">postgres</property>
<property name="hibernate.connection.password">password</property>
<!-- Other Hibernate properties -->
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<!-- first time it is create and then onwards update -->
<property name="hbm2ddl.auto">update</property>
<!-- Mapping files or annotated classes -->
<!-- Add your entity classes or mapping files here for ex: entity used below -->
<mapping class="dev.engel.example.Worker"/>
</session-factory>
</hibernate-configuration>
Этот файл можно использовать как есть, кроме свойств с именем hibernate.connection.*. Думаю тут очевидно - если у ваc не postgres - указываете свое, адрес, порт и database тоже свои. Ну и креды пользователя, с которыми вы будете ходить в базу, разумеется свои. Также обратите внимание на строчку
<mapping class="dev.engel.example.Worker"/>
Это собственно и есть класс, который hibernate свяжет с конкретной таблицей в базе данных. Создаем этот файл. Создать его можно где угодно, но потом его полное имя надо занести сюда.
Создаем класс dev.engel.example.Worker
package dev.engel.example;
import jakarta.persistence.*;
@Entity
@Table(name = "workers")
public class Worker {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;
@Column(name = "FirstName") private String FirstName;
@Column(name = "SecondName") private String SecondName;
// Getters and setters, constructors, etc.
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getFirstName() { return FirstName; }
public void setFirstName(String FirstName) { this.FirstName = FirstName; }
public String getSecondName() { return SecondName; }
public void setSecondName(String SecondName) { this.SecondName = SecondName; }
}
Немного пояснений. Для того, чтобы hibernate смог связать класс с таблицей БД, необходимо, чтобы были
@Entity - аннотация поясняющая, что эта сущность будет связываться таблицей БД
@Table - аннотация описывающая с какой именно таблицей БД этот класс будет ассоциирован. Если у аннотации нет параметров вообще - значит имя таблицы будет предполагаться равным имени класса. Иначе - то, что указано в параметрах
Как минимум одно поле с аннотацией @Id
Как минимум одно поле с аннотацией @Column - в параметрах указывается точное название поля БД
Разумеется, все это счастье обкладываем геттерами и сеттерами - для удобства. На этом минимальная подготовка окружения закончена.
Что теперь с этим делать
У нас по дефолту создается класс Main. Давайте поиспользуем его:
Создаем метод getRows()
Вызываем его и main()
public static void main(String[] args) { getRows();
}
public static void getRows() {
SessionFactory sessionFactory = new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
Session session = sessionFactory.openSession();
session.getTransaction().begin();
List<Worker> employees = session.createQuery("FROM Worker", Worker.class).getResultList();
for (Worker employee : employees) {
System.out.println(
"ID: " + employee.getId() +
", FirstName: " + employee.getFirstName() +
", SecondName: " + employee.getSecondName());
}
session.getTransaction().commit();
session.close();
sessionFactory.close();
}
Запускаем и смотрим что получилось:
Hibernate:
select
w1_0.id,
w1_0.FirstName,
w1_0.SecondName
from
workers w1_0
В логе мы увидим команду, которую выполнил hibernate. И выполнил успешно. Тут наиболее внимательные заметят - ведь такую таблицу мы не создавали, а тут никакой ошибки. Возвращаемся к конфигурационному файлу, и смотрим на строку
<!-- first time it is create and then onwards update --> <property name="hbm2ddl.auto">update</property>
Она означает, что если вдруг на момент обращения к указанной таблице ее не существует - она будет создана. Если такое поведение системы вас не устраивает - удалите указанную строку и при отсутствии нужной таблицы программа будет падать.
Кстати, неспроста в коде есть вывод результата запроса. При первом запуске в результате ничего не пришло (создалась только пустая таблица), поэтому и вывода никакого.
Добавим метод:
public static void addRow() { SessionFactory sessionFactory = new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
Session session = sessionFactory.openSession();
Worker e0 = new Worker();
e0.setId(0L);
e0.setFirstName("Иванов");
e0.setSecondName("Иван");
Worker e1 = new Worker();
e1.setId(1L);
e1.setFirstName("Петров");
e1.setSecondName("Петр");
Worker e2 = new Worker();
e2.setId(2L);
e2.setFirstName("Сидоров");
e2.setSecondName("Сидор");
session.getTransaction().begin();
session.save(e0);
session.save(e1);
session.save(e2);
session.getTransaction().commit();
session.close();
sessionFactory.close();
}
... и вызовем его из main().
Теперь в логе видим другие запросы, которые выполнил hibernate
Hibernate:
insert
into
workers
(FirstName, SecondName)
values
(?, ?)
Hibernate:
insert
into
workers
(FirstName, SecondName)
values
(?, ?)
Hibernate:
insert
into
workers
(FirstName, SecondName)
values
(?, ?)
Теперь повторим вызом метода getRows()
Hibernate:
select
w1_0.id,
w1_0.FirstName,
w1_0.SecondName
from
workers w1_0
ID: 1, FirstName: Иванов, SecondName: Иван
ID: 2, FirstName: Петров, SecondName: Петр
ID: 3, FirstName: Сидоров, SecondName: Сидор
Мы снова видим запрос, который выполнил hibernate, но в этот раз он уже вернулся не пустым. Результат содержит то, что мы записали в таблицу.
У меня не было цели описать все, что можно сделать с помощью hibernate - но работая с этим примером начинающий разработчик сможет
Понять о чем это вообще
На простом примере попробовать подергать БД
Сформулировать правильные вопросы к "старшим" товарищам или к Гуглу.
Желаю всем успехов в постижении этого ремесла.