Перейти к содержимому

Как подключить hibernate к java проекту

  • автор:

Пример Hibernate

Рассмотрим разработку Hibernate примера в среде Eclipse. Основная цель, которую будем преследовать в данном Hibernate примере — показать технологию использования библиотеки по записи объектов в таблицу БД, чтению объектов таблицы, поиску объекта по идентификатору записи ID.

На следующем скриншоте представлена структура проекта HibernateExample в среде разработки IDE Eclipse.

Hibernate пример включает :

  • класс тестирования PersonTest.java;
  • объект/класс Person.java;
  • файл описания (mapping) класса person.hbm.xml
  • файл конфигурации hibernate.cfg.xml, включающий описание подключения к серверу БД;
  • библиотеки директории lib.

В качестве СУБД в примере будем использовать MySQL. В БД создадим таблицу «test.person» в схеме «test». Конечно, таблицу можно было бы также создать с использованием Hibernate, но в данном примере мы это не будем рассматривать.

Исходный код примера можно скачать здесь.

Описание таблицы базы данных
CREATE TABLE test.person ( id INT (11) NOT NULL, name VARCHAR (128) NOT NULL, PRIMARY KEY (id) ) ENGINE = INNODB CHARACTER SET utf8 COLLATE utf8_general_ci;

Тестовая таблица «person» будет включать два поля : идентификатор записи «id» и имя «name». Записи в таблице будут храниться в кодировке «UTF8».

Исходный код объекта/класса

Создадим класс Person с полями id — идентификатор записи и name — имя. Класс, с которым работает Hibernate, называется сущностью Entity. Для того, чтобы класс Person стал сущностью, добавим аннотацию @Entity. Сущности типа Person будут храниться в таблице, имя которой совпадает с именем класса, т.е. «person». Значения полей сущностей будут храниться в одноименных колонках этой же таблицы. Сущность должна иметь «persistence identity», или идентификатор. Это — ключ, который однозначно её идентифицирует и выделяет среди других сущностей такого же типа. Идентификатор указывается с помощью аннотации @Id. В классе «Person» в качестве идентификатора можно использовать поле id, которое соответствует колонке первичного ключа в таблице «test.person».

import javax.persistence.Entity; import javax.persistence.Id; @Entity public class Person < @Id int id; String name; public Person() <>public Person(int id, String name) < super(); this.id = id; this.name = name; >public int getId() < return id; >public void setId(int id) < this.id = id; >public String getName() < return name; >public void setName(String name) < this.name = name; >public String toString() < return "Person "; > >
Конфигурационный файл объекта
Конфигурационный файл hibernate.cfg.xml

Конфигурационный XML-файл hibernate.cfg.xml определяет параметры СУБД, учетную запись (login, password) подключения к серверу БД, а также дополнительные параметры, которые используются при работе с сервером.

     com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/test root password 1 true org.hibernate.dialect.MySQLDialect thread utf8 utf8 true   

В файле конфигурации hibernate.cfg.xml определена база данных MySQL, пул подключений — 1 соединение. В свойстве «show_sql» устанавливаем истиное значение, чтобы в консоли были отображены генерируемые библиотекой Hibernate SQL-скрипты. Дополнительно устанавливаем кодировку записей UTF8, чтобы можно было бы работать с кириллицей.

Тестирование Hibernate примера

Создадим класс «PersonTest» для проверки работы библиотеки. В методе main() вызывается конструктор класса, в котором вызывается метод createHibernateSession() для создания сессии Session. Если сессия создана успешно, то в методе recordsAdd() в таблицу БД добавляются два объекта. Подробно о состоянии сущности, сессии Session, ее методах перевода сущности из одного состояния в другое, представлено здесь.

После создания сессии в методе recordsRead() объекты из БД «загружаются» в коллекцию и отображаются в консоли. В заключении программа вызывает метод recordFind(final int id) для поиска в таблице БД объекта по идентификатору записи и завершает работу — закрывает сессию.

import java.util.List; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import net.common.model.Person; public class PersonTest < private Session session = null; private final String[][] persons = , >; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** * Процедура создания сессии * @return org.hibernate.Session */ private Session createHibernateSession() < SessionFactory sessionFactory = null; ServiceRegistry serviceRegistry = null; try < try < Configuration cfg = new Configuration(). addResource("person.hbm.xml").configure(); serviceRegistry = new StandardServiceRegistryBuilder(). applySettings(cfg.getProperties()).build(); sessionFactory = cfg.buildSessionFactory(serviceRegistry); >catch (Throwable e) < System.err.println("Failed to create sessionFactory object." + e); throw new ExceptionInInitializerError(e); >session = sessionFactory.openSession(); System.out.println("Создание сессии"); > catch (Exception e) < System.out.println(e.getMessage()); >return session; > //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** * Процедура добавления записей в таблицу */ private void recordsAdd() < try < System.out.println("Добавление записи в таблицу БД"); Transaction tx = session.beginTransaction(); for (int i = 0; i < persons.length; i++) < Person person = new Person(); person.setId(Integer.valueOf(persons[i][0])); person.setName(persons[i][1]); session.save(person); >tx.commit(); System.out.println("\tЗаписи добавлены"); > catch (Exception e) < System.out.println(e.getMessage()); >> //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** * Процедура чтения записей */ private void recordsRead() < System.out.println("\nЧтение записей таблицы"); String query = "select p from " + Person.class.getSimpleName() + " p"; @SuppressWarnings("unchecked") Listlist = (List)session.createQuery(query).list(); System.out.println(list); > //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** * Процедура поиска записи */ private void recordFind(final int id) < System.out.println("\nЧтение записи таблицы по ID"); Person person = (Person) session.load(Person.class, id); System.out.println(person); >//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** * Конструктор класса */ public PersonTest() < // Создание сессии session = createHibernateSession(); if (session != null) < // Добавление записей в таблицу recordsAdd(); // Чтение записей таблицы recordsRead(); // Поиск записи по идентификатору recordFind(Integer.valueOf(persons[1][0])); // Закрытие сессии if (session.isOpen()) session.close(); >> //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public static void main(String[] args) < new PersonTest(); System.exit(0); >>

Для того, чтобы действия над сущностями сохранялись в базе данных, методы для создания, изменения и удаления сущностей должны вызываться в транзакциях. Для открытия и закрытия транзакций используются методы beginTransaction() и commit() объекта Transaction

Следует обратить внимание на то, как объект сохраняется в таблице БД, как читается список объектов и как выполняется поиск объекта по идентификатору.

// сохранение объекта в таблице : recordsAdd() session.save(person); // чтение списка объектов : recordsRead List list = (List)session.createQuery(query).list(); // чтение объекта по идентификатору : recordFind Person person = (Person) session.load(Person.class, id);

В консоли будут отражены следующие результаты работы приложения :

Создание сессии Добавление записи в таблицу БД Hibernate: insert into person (Name, id) values (?, ?) Hibernate: insert into person (Name, id) values (?, ?) Записи добавлены Чтение записей таблицы Hibernate: select person0_.id as id1_0_, person0_.Name as Name2_0_ from person person0_ [Person , Person ] Чтение записи таблицы по ID Person

Автоматически генерируемые библиотекой SQL-скрипты отображены в консоли после ключевого слова «Hibernate». Чтобы блокировать «вывод» SQL-скриптов необходимо свойству «show_sql» в файле конфигурации присвоить значение false.

Пример использования генератора последовательностей Sequence в Hibernate можно увидеть здесь.

Описание аннотаций связей между сущностями с примерами представлено здесь.

Hibernate для начинающих

Я сталкивался (да и не только я) с проблемой развертывания Hibernate и решил попробовать осветить данную тему. Hibernate — это популярный framework, цель которого связать ООП и реляционную базу данных. Работа с Hibernate сократит время разработки проекта в сравнении с обычным jdbc.

Для новичка программирования настройка framework часто вызывает затруднения. Помощь комьюнити с освещением базовых проблем поможет начинающим осваивать языки программирования быстрее. Статья предназначена только для начинающих в Java, которые впервые развертывают hibernate. Я развертывал hibernate на базе лицензионной IDEA.
Maven framework для автоматизации сборки проекта на основе POM, позволяющая подключать из интернета зависимости, не скачивая библиотеки в проект. POM (project object model) -декларативное описание проекта. Копируем название библиотек в xml формате с сайта mvnrepository.com.

Для начала создаёте структуру проекта maven:

hibernateMaven

Потом в pom.xml вставляем. Нам понадобятся две зависимости: hibernate-core и mysql-connector, но если вы хотите больше функционала — вы должны подключить больше зависимостей.

Существуют стандартные рекомендации подключать зависимости по отдельности, но я так не делаю.

 5.0.1.Final    mysql mysql-connector-java 5.1.34    org.hibernate hibernate-core $  org.hibernate hibernate-entitymanager $ 

И щелкаем на Import Changes Enable Auto-Import, автоматически импортируя изменения.

image

Подключаемся к базе данных, которая развернута на локальном компьютере, выбираем поставщика баз данных MySQL.

image

Вводим имя базы данных, имя пользователя и пароль. Протестируйте соединение.

image

Выбираем проект и через framework support просим у хибернейта создать за нас Entity файлы и классы с Getter и Setter.

image

image

Выбираем Generate Persistence Mapping через кладку Persistence, выбираем jenerate Persistance Mapping, а в появившемся окне прописываем схему базы данных, выбираем prefix и
sufix к автоматически сгенерированным названиям. Будут сгенерированы названия xml файлов и классов с аннотациями:

image

Раскидайте файлы в таком порядке: .xml-файлы должны находится в папке с ресурсами, а сущности в папке java.

image

Дописываем в hibernate.cfg username и password (звёзды поставил я, а так пишите обычным шрифтом).

image

Вот и все! Дальше через класс main запускаем проект.

Это моя первая статья. Рассчитываю на здравую критику.

Что такое Hibernate Framework в Java и как его использовать?

Сегодня мы рассмотрим важный инструмент для взаимодействия с базами данных — Hibernate. Вы узнаете что это за библиотека, в каких случаях и как используется, а также как реализована работа с БД в Java.

Курс Python.

Цю мову програмування використовують від базових концепцій до складних застосувань у сферах штучного інтелекту. Після проходження курсу гарантовано отримай роботу в ІТ.

БД мем

Но перед тем, как перейти к разговору о самом Hibernate, нужно сказать пару слов о том, что означает ORM, JDBC и некоторых принципах работы с БД.

JDBC — API: управление запросами к СУБД

Когда Java-программа устанавливает связь с базой данных, она не посылает запросы к таблицам напрямую, а использует программный интерфейс JDBC (Java Database Connectivity). Подключение к БД и дальнейшее взаимодействие с ней происходит через специальные драйверы. Вместо того, чтобы создавать отдельный набор методов и процедур, которые будут работать с конкретной базой данных (как например, это сделано в PHP — где есть отдельные наборы процедур для MySQL, Postgres и прочих БД), в Java был придуман единый интерфейс.

Он позволяет любой Java-программе иметь дело с разными реляционными базами через абсолютно одинаковые методы. Чтобы в каждом случае работа шла с едиными методами, должны быть задействованы JDBC-драйверы. Динамически подгружаясь по ходу выполнения приложения, такой драйвер автоматически инициализируется и вызывается, когда приложение запрашивает URL, включающий протокол, за который ответственен драйвер.

Код обычного драйвера JDBC MySQL под платформу Linux имеет вид:

Курс Front-end Basic.

Оволодій навичками розробки веб-інтерфейсів та стань справжнім Front-end розробником! Заробляй від 800$ на початку карʼєри.

package javaapplication1; import java.sql.*; public class Main < public static void main(String[] args) throws SQLException < /** * Этот код выполняет загрузку драйвера DB. */ //Class.forName("com.mysql.jdbc.Driver"); Connection conn = null; try < conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/db_name", "user", "password"); if (conn == null) < System.out.println("Отсутствует коннект с БД!"); System.exit(0); >Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM users"); while (rs.next()) < System.out.println(rs.getRow() + ". " + rs.getString("firstname") + "\t" + rs.getString("lastname")); >stmt.close(); > catch (SQLException e) < e.printStackTrace(); >finally < if (conn != null)< conn.close(); >> > >

При переключении с одной БД на другую, работа Java-программы никак не меняется, что выгодно отличает эту реализацию от, скажем, языка PHP, где переход с одной БД на другую требует от разработчиков переписывания целого слоя работы с базой данных (с использованием других методов).

Обязанность по созданию JDBC-драйвера лежит на вендоре базы данных. К любой БД такой драйвер уже существует и поддерживается разработчиком, его легко можно найти в интернете.

Набор операций JDBC стандартный и очень простой:

    подключились к базе данных;

Существует ряд фундаментальных проблем, связанных с работой языка Java с реляционными БД. Язык Java использует парадигму ООП, поэтому мы все время имеем дело с объектами. В то же время реляционные базы данных оперируют таблицами.

Объекты в Java и таблицы в БД — это разные сущности, которые сложно между собой сопоставить. С другой стороны, для решения задач нам постоянно нужно каким-то образом объекты превращать в таблицы и наоборот. Задача нетривиальная, решить которую сложно — нужно писать некоторую логику, используя тот же самый JDBC.

Курс Front-end Basic.

Оволодій навичками розробки веб-інтерфейсів та стань справжнім Front-end розробником! Заробляй від 800$ на початку карʼєри.

Преимущества JDBC:

  • единый интерфейс для работы СУБД, одни и те же классы для всех БД;
  • простой синтаксис;
  • кроссплатформенное решение (MacOS, Linux, Windows);

Недостатки JDBC:

  • не годится для больших проектов;
  • сложно использовать концепцию MVC;
  • возможны трудности при переходе от одной СУБД к другой (с имеющимся кодом);
  • отличия в синтаксисе SQL-запросов.

Курс Front-end Basic.

Оволодій навичками розробки веб-інтерфейсів та стань справжнім Front-end розробником! Заробляй від 800$ на початку карʼєри.

В простых случаях применять JDBC не сложно (например, был объект «Пользователь», и для того, чтобы записать его в базу данных, мы из некоторой строки достаем id, имя и т.д.). Но если мы будем иметь дело со сложным графом объектов, сохранить его в базу данных будет уже не так легко — придется писать длинный код SQL, который потом проверить будет очень сложно. Кроме того, мы имеем дело в Java классом based object oriented language , где есть наследование, а в таблицах нет никакого наследования.

Если вы пишете серьезное приложение, то вы будете работать с кодом на огромное число строк. Вся современная бэкенд-разработка — это работа с большим количеством информации. Как следствие — разработчик имеет дело с постоянными запросами к БД. Ему необходимо чуть ли не в каждой строчке написать connect , получить, извлечь данные из базы, затем строки и цифры нужно разложить по полям объектов. Серьезный enterprise -объект может содержать до десяти тысяч полей и, соответственно, у вас будет десять тысяч строк. Ситуация осложняется тем, что такие объекты постоянно меняются — по этой причине приходится решать массу проблем.

Что такое Hibernate в Java и для чего он нужен

Объектная модель данных и модель данных в реляционных таблицах не очень совпадают. Имеется некая логика сравнения объектов, и никто не гарантирует, что эта логика совпадает и в базе данных, и в приложении. Это может приводить к большому числу ошибок.

Например, вы создали нового пользователя, поместили его в базу данных, а затем вдруг оказалось, что в базе данных он считается другим пользователем из-за того, что там критерии сравнения другие.

Мы обязаны следить, чтобы в объектной модели Java и той, которая хранится в базе, сущности совпадали, чтобы была одна и та же логика сравнения.

В объектной модели данных Java также имеются некие дополнительные возможности — например, разные уровни доступа к разным полям. Некоторые поля мы бы не хотели иметь в БД, некоторые мы бы не хотели извлекать или записывать.

Чтобы не кодить лишний раз и думать про JDBC, была взята концепция ORM.

Object-Relational Mapping — это механизм, который позволяет отображать данные из реляционных баз данных в виде объектов. ORM-системы упрощают работу с базами данных, уменьшая необходимость руководствоваться SQL-командами.

orm

Все фреймворки в Java стандартизированы и работают на строгих спецификациях. Это нужно, чтобы не было хаоса и разных трактовок той или иной технологии. Такой принцип во многом похож на ООП, когда мы сначала создаем интерфейс, что по сути — спецификация или правило работы объектов, и только потом мы создаем любое количество реализаций.

В Java присутствует спецификация JPA (Java Persistence API). Она определяет способы для управления данными и содержит инструменты:

  • CRUD API — программный интерфейс для обращения к популярным методам объекта который хранится в БД ( insert , select и пр.), стандартных операций (создание, чтение, обновление и удаление).
  • Объектно-ориентированный язык запросов. Некий доменный язык, похожий на SQL — удобный, чтобы говорить про объекты (а не про таблицы).

Чтобы реализовать JPA нам понадобится так называемые JPA-провайдеры — библиотеки, которые его реализуют.

Таких провайдеров существует много для разных языков программирования:

  • Enterprise JavaBeans Entity Beans
  • Java Data Objects
  • Castor
  • TopLink
  • Spring DAO
  • MyBatis
  • Hibernate

Более половины имплементаций JPA выполнено на фреймворке Hibernate с открытым кодом, чем объясняется популярность этой библиотеки.

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

Другими словами: производится объектно-реляционный мэппинг (ORM). Благодаря Hibernate (который использует программный интерфейс JDBC) программисты не задумываются, как поля из базы данных попадают в поля объектов.

Особенности Hibernate

nhibernate

Для работы Hibernate использует HQL — эквивалент языка SQL, только с учетом Java-классов. Фреймворк может применяться в любом типе приложений — desktop/web, Spring и так далее. Сегодня Hibernate портирован на другие языки, например, в C# (.NET) используется Nhibernate.

Еще одна из особенностей Hibernate — механизм «ленивой загрузки». Он позволяет отложить загрузку связанных сущностей, пока они не будут явно использованы. Отложенные SQL-запросы будут выполняться только тогда, когда связанные сущности (ключи) будут явно использованы.

Подведем итог. Hibernate применяется в Java-разработке, когда возникает необходимость перенести из базы данных информацию в код и как-то ее обработать. Этот фреймворк помогает оптимизировать низкоуровневый код, ускорив его написание и сделав его более компактным и удобным для разработчиков.

Что нужно для начала использования Hibernate

Схема работы нашего приложения выглядит, примерно, следующим образом:

hibernate

Программа общается с базой данных посредством Hibernate через JDBC-коннектор, используя конфигурацию conf . В этих конфигурационных параметрах указано, как Hibernate должен передавать данные.

Представление Java-классов с таблицами БД реализуется посредством XML-файлов с конфигурациями либо через Java-аннотации.

Когда данных много, связи между сущностями добавляют головной боли. В Hibernate есть стандартный набор связей, которые могут понадобиться:

  • One-to-one
  • One-to-many (many-to-one)
  • Many-to-many

Перед тем, как приступить к работе с Hibernate, вам нужно изучить:

  • JDBC
  • SQL
  • ООП
  • XML
  • Аннотации в Java
  • Разобраться с настройками параметров проекта в IDE

Обычно, для создания любого приложения в Hibernate необходимо выполнить следующие действия:

1. Создать проект и подключить зависимости.
2. Добавить параметры для работы Hibernate.
3. Выполнить представление (мapping) классов для связывания таблиц БД с кодом.
4. Создать SQL-запросы для бизнес-процессов ( select , update , delete и т.д.)
5. Обработать результаты запросов.
6. Представить результаты в нужном формате во внешнем графическом интерфейсе (web, Android, десктопное приложение и т.д.).

Кэширование в Hibernate

Один из способов оптимизации и ускорения работы приложения — кэширование.

В Hibernate используется три уровня кэшей:

  1. Кэш первого уровня (сессионный) — это то, что включено по умолчанию, работает всегда и то, что нельзя отключить. Он выполняет кэширование сущностей сохраняя в persistence context . Допустим, вы хотите выгрузить сущность из БД. Она выгружается один раз и попадает в persistence context . Вы тут же хотите выгрузить еще раз, и Hibernate уже не обратится к БД, а возьмет из persistence context . При работе с этим типом кэширования нередко возникают сайд-эффекты. Например, он хорошо работает через EntityManager . Но бывает так, что если вы меняете сущности вне EntityManager , кто-нибудь в другой транзакции обращается к БД и меняет сущность. В первой транзакции она выгружена и, если вы захотите проверить, является ли она подходящей под ваши параметры, сущность уже будет иной. Вам про это будет неизвестно, потому что у вас будет задействован кэш первого уровня.
  2. Кэш второго уровня — примерно то же самое. Он должен быть явно включен и настроен. Кэш второго уровня привязан к объекту-фабрике сессий (Session Factory Object). Среди вариантов реализации кэша второго уровня: EHCache, OSCache, SwarmCache, JBoss, TreeCache.
  3. Кэш третьего уровня (кэш запросов) — кэширует результаты запросов по запросу и его параметрам. Он сохраняет не сами объекты целиком, а их id. Поэтому, чтобы их получить, ему удобнее связаться через кэш второго уровня, чем делать запросы в БД.

Преимущества и недостатки Hibernate

Hibernate, безусловно, удобен. Самые популярные IDE (среды разработки) поддерживают этот фреймворк через плагины. Но хотя библиотека и помогает нам убрать «спагетти» из кода, упростив его, она все же имеет ряд недостатков:

  • Hibernate — довольно громоздкое решение, поэтому при некорректных параметрах в крупных проектах, где идет работа с большим количеством объектов, возможно снижение производительности.
  • Для JPA и Hibernate есть определенный набор API, который следует изучить.
  • При работе с библиотекой на низком уровне у вас меньше контроля доступа к БД.

В Hibernate часто встречаются конфигурации по умолчанию — имена таблиц, столбцов и т.д. Кроме того, для некоторых параметров фреймворк сам «догадывается» про требуемое значение.

Например, вы можете забыть сделать аннотацию и Hibernate может сам попробовать связать сущности через дополнительную таблицу. При этом он сделает предположение, как именно должна называться эта промежуточная таблица.

Создаем проект и настраиваем Hibernate

Поскольку у Hibernate — не одна библиотека, а несколько, следует их все подключить. Наш проект будем использовать со сборщиком Maven, который будет отвечать за загрузку необходимых нам библиотек.

Maven

Maven создаст структуру проекта, и Hibernate будет ее использовать, включая конфигурационный файл проекта pom.xml , содержащий информацию о зависимостях и прочие опции. Внутри папки java будем писать java-классы, в папке resources будут находится все файлы конфигурации Hibernate.

Файл pom.XML выглядит так:

  4.0.0 com.app.HibernateTest QuickStart 1.0-SNAPSHOT 19 19  

В разделе зависимостей ( dependency ) мы должны указать, что мы будем работать с Hibernate:

maven rep

Переходим на https://mvnrepository.com/ и вводим в поиске Hibernate Core. Выбираем версию, наш сборщик, затем копируем зависимости и вставляем в файл pom.xml :

  org.hibernate hibernate-core 6.1.6.Final pom 

Далее по поиску в репозитории ищем соответствующие зависимости для коннектора БД и вставляем их тоже:

  mysql mysql-connector-java 8.0.32 

Принципиального значения, какую брать версию — нет, но вы должны понимать, что если что-то не работает или работает не так, как хотелось, возможно, следует попробовать другую. К сожалению, часто возникают ошибки.

Создадим класс Student , содержащий поля, которые нужно промапить. Добавим публичный конструктор и переопределим метод:

package com.app.pojo; public class Student < private int id; private String name; private int age; public Student()<>public int getId() < return id; >public void setId(int id) < this.id = id; >public String getName() < return name; >public void setName(String name) < this.name = name; >public int getAge() < return age; >public void setAge(int age) < this.age = age; >@Override public String toString() < return "StudentПеред началом работы с базой пропишите параметры в файле hibernate.cfg в каталоге resources. Есть еще альтернативный вариант с xml-настройками — через файл persistence.xml. Он применяется для любой реализации JPA (в том числе и Hibernate), но он, понятное дело, ограничен спецификацией JPA.

Создадим hibernate.cfg:

     com.mysql.cj.jdbc.Driver com.mysql.jdbc.Driverjdbc:mysql://localhost:3306/mydb //Путь, по которому будет идти запрос при обращении к базе данных (для данного примера - testdatabase на порту 3306, имя БД - mydb) org.hibernate.dialect.MySQL8Dialect root //Пользователь root //Пароль 3 org.hibernate.dialect.MySQLDialectthread true//отображение SQL-запросов; true update //Поле, необходимое для того, чтобы дать разрешение Hibernate на обновление данных в БД. Если данных не будет, он их создаст.  

Внутри конфигурационного файла создается секция session-factory — фреймворк открывает сессию, в течение которой делает запросы. Как только сессия будет закончена, он ее будет закрывать. Порядок свойств ( property ) в конфигурационном файле не имеет значения.

Для получения сессии можно использовать два главных объекта — SessionFactory (в JPA — EntityManagerFactory ) и Session (в JPA — EntityManager ). SessionFactory создается только один раз при запуске приложения, он настривать, работать с сессиями. При создании SessionFactory считываются параметры hibernate.cfg.xml .

Создадим еще один класс — наше Java-приложение App . Id для студента создавать не будем, этот идентификатор будет автоматически создаваться в БД одновременно с появлением новой записи.

Обратите внимание: уникальный ключ должен быть всегда, если мы его создаем, в БД он создаваться не должен, иначе в базе данных будут ошибки.

Мы хотим передать данные нашего студента в таблицу. Соответственно, нам желательно было бы написать что-то простое, например save(Serge) :

package com.app; import com.app.pojo.Student import org.hibernate.cfg.Configuration; public class App < public static void main(String[] args) < Student Serge = new Student(); Serge.setName("Serge"); Serge.setAge(10); //Serge.setId(); Configuration con = new Configuration().configure; con.addAnnotatedClass (Student.class); StandardServiceRegistryBuilder sBilder = new StandardServiceRegistryBuilder() .applySettings(con.getProperties()); SessionFactory sf = con.buildSessionFactory(sBilder.build()); >>

Пример создания CRUD-приложения (Create, Read, Update, Delete)

Если это необходимо, в конфигурационном файле мы можем написать, сколько фабрика сессий может генерировать потоков для работы с клиентами. После того, как фабрика сессий прописана, можем переходить к CRUD.

Create

Начнем с команды Create :

public class App < public static void main(String[] args) < Student Serge = new Student(); Serge.setName("Serge"); Serge.setAge(10); //Serge.setId(); Configuration con = new Configuration().configure; con.addAnnotatedClass (Student.class); StandardServiceRegistryBuilder sBilder = new StandardServiceRegistryBuilder() .applySettings(con.getProperties()); SessionFactory sf = con.buildSessionFactory(sBilder.build()); //create Session sessionCreate = sf.openSession(); Transaction trCreate = sessionCreate.beginTransaction;//Начало транзакции sessionCreate.save(Serge); trCreate.commit(); sessionCreate.close();//Завершение транзакции >>

Напомним, транзакции позволяют сохранять состояние базы данных. Они удостоверяют, что изменения, сделанные в рамках транзакции, сохранятся, или, наоборот — изменения, сделанные в рамках транзакции, будут отклонены.

Поэтому между созданием и коммитом транзакции мы можем сохранять сразу несколько объектов. Посмотрим, как работает теперь наше приложение. Возьмем базу данных (принципиального значения, что это будет за БД не имеет), подключимся к ней и посмотрим на результат:

db

Для просмотра подойдет какая-нибудь внешняя программа, например, MySQL Workbench, а можно подключиться к ней прямо в среде разработки IDE (скажем, в IntelliJ IDEA):

MYSQL

В БД появились новые колонки и пользователь Serge . Значение id присвоено автоматически. При повторном добавлении пользователя автоматически присваивается новый id. Помимо основной таблицы Hibernate создал также еще одну — hibernate_sequence . Это промежуточная таблица, в которой хранится инкрементируемое значение value .

Read

Транзакция прошла, данные добавлены. Переходим к команде Read и открываем новую сессию:

//read Session sessionRead = sf.openSession(); Transaction trRead = sessionRead.beginTransaction(); Student student1 = sessionRead.find(Student.class, o:1); System.out.println(student1.toString()); trRead.commit(); sessionCreate.close();

Результат вывода в консоль:

Update

Следующая команда Update :

//update Session sessionUpdate = sf.openSession(); Transaction trUpdate = sessionUpdate.beginTransaction(); Student student2 = sessionUpdate.find(Student.class, o:2); student2.setAge(20); student2.setName("Alexander"); sessionUpdate.update(student2); trUpdate.commit(); sessionUpdate.close();

Пользователь в базе данных обновит свое имя и значение Age.

Delete

Последняя транзакция — Delete :

//delete Session sessionDelete = sf.openSession(); Transaction trDelete = sessionDelete.beginTransaction(); sessionDelete.delete(student2); txDelete.commit(); sessionDelete.close();

Запись в таблице будет уничтожена.

Заключение

Hibernate — это удобный, мощный и эффективный ORM-фреймворк. Он прост в изучении и существенно экономит время при разработке ПО, в котором идет обращение к базам данных. Используя его, программист может сосредоточиться на основной логике, сократив написание запросов к минимуму.

Как видите, в приложении Hibernate нет ничего сложно. Главная трудность, с которой вам придется столкнуться — правильная настройка зависимостей и конфигурационных файлов проекта. Также важно правильно пользоваться инструментами для автоматизации сборки проектов: Mavеn, Gradle и другими.

Ссылки с конфигурациями в репозиториях постоянно меняются, поэтому будьте внимательны и, если что-то не работает — проверьте их актуальность.

Стабильность работы приложения на Hibernate во многом зависит от версии Java и используемых модулей (например, Hibernate 6.1.3 с Java 17 вызывает ошибки, а та же версия, но уже с Java 18 работает нормально).

В заключение рекомендуем посмотреть замечательный курс по основам работы Hibernate:

Курс UI/UX для геймдеву.

Під час навчання ви розробите проекти для портфоліо, що складається з 5 ключових аспектів UX/UI-дизайну, та отримаєш необхідні навички для професійного росту.

Ваше первое приложение на Hibernate

Java-университет

Ваше первое приложение на Hibernate - 1

В этой статье вы познакомитесь с одним из наиболее популярных enterprise-фреймворков для Java и создадите свое первое приложение на Hibernate. Никогда не слышали о Hibernate? Может быть, слышали о нем, но не пользовались? Или пытались начать, но не получилось? Во всех трех случаях — добро пожаловать под кат:) Всем привет! В этой статье я расскажу об основных особенностях фреймворка Hibernate и помогу вам написать свое первое мини-приложение. Для этого нам понадобятся:

  1. Intellij Idea Ultimate Edition;
    Качаем с официального сайта и активируем 30-дневную пробную версию.
  2. PostgeSQL — одна из самых популярных современных систем управления базами данных (СУБД);
  3. Maven (уже зашит в IDEA);
  4. Немного терпения.

Статья ориентирована прежде всего на тех, кто никогда не работал с данной технологией, поэтому количество кода было максимально уменьшено. Приступим!

Что такое Hibernate?

Это — одна из наиболее популярных реализаций ORM-модели. Объектно-реляционная модель описывает отношения между программными объектами и записями в БД. Конечно, функционал Hibernate очень широк, но мы остановимся на самых простых функциях. Наша цель: создать CRUD-приложение (Create,Read,Update,Delete), которое будет уметь:

  1. Создавать пользователей (User), а также искать их в базе данных по ID, обновлять их данные в базе, а также удалять из базы.
  2. Присваивать пользователям объекты автомобилей (Auto). Создавать, редактировать, находить и удалять автомобили из базы данных.
  3. Кроме того, приложение должно автоматически удалять "бесхозные" автомобили из БД. Т.е. при удалении пользователя, все принадлежащии ему автомобили также должны быть удалены из БД.

Структура нашего проекта будет следующей: Ваше первое приложение на Hibernate - 2Как видите, ничего сложного. 6 классов + 1 файл с конфигами. Для начала, создадим новый maven-проект в Intellij Idea. File -> New Project. Из предлагаемых типов проектов выбирайте Maven и переходите дальше.Ваше первое приложение на Hibernate - 3Apache Maven — фреймворк для автоматизации сборки проектов на основе описания их структуры в файлах на языке POM. Вся структура вашего проекта будет описана в файле pom.xml, который IDEA сама создаст в корне вашего проекта. В настройках проекта вам нужно будет указать параметры Maven — groupId и artifactId. Обычно в проектах groupId наименование организации или подразделения, туда записывают доменное имя организации или сайта проекта. В свою очередь artifactId — название проекта. Для groupdId можете указать com.вашНикнейм.javarush , на работу приложения это никак не повлияет. Для artifactId выберите любое понравившееся вам название проекта. Version тоже можете оставить без изменений.Ваше первое приложение на Hibernate - 4На последнем экране просто подтвердите ранее введенные данные.Ваше первое приложение на Hibernate - 5Итак, проект мы создали, осталось всего ничего — написать код и заставить его работать 🙂 Прежде всего, если мы хотим создать приложение, работающие с базой данных — нам определенно не обойтись без базы данных! Качаем PostgreSQL отсюда (я использую 9 версию). В PostgreSQL имеется созданный по умолчанию пользователь 'postgres', пароль для него вам нужно будет придумать при установке. Не забывайте пароль, он нам понадобится позже! (Вообще, пользоваться дефолтной БД в приложениях — bad practice, но с целью сократить объем геморроя с созданием своей БД обойдемся ей). Если вы не дружите с командной строкой и SQL-запросами — есть хорошая новость. Intellij IDEA предоставляет вполне годный пользовательский интерфейс для работы с БД. Выглядит он так:Ваше первое приложение на Hibernate - 6(находится на правой боковой панели IDEA, вкладка Database) Для создания поключения нажмите "+", выберите нашего провайдера (PostgeSQL). Заполните поля с пользователем, именем БД (и то и другое — postgres) и введите пароль, который задали при установке PostgreSQL. При необходимости — скачайте драйвер Postgres, это можно сделать на этой же странице. Намжмите "Test Connection", чтобы проверить, что соединение с БД установлено. Если видите надпись "Successful" — едем дальше. Теперь создадим нужные нам таблицы. Всего их будет две — users и autos. Параметры для таблицы users: Ваше первое приложение на Hibernate - 7Обратите внимание на то, что id является первичным ключом (Primary Key). Если не знаете что такое первичный ключ в SQL — гугл, это важно. Настройка для таблицы autos: Ваше первое приложение на Hibernate - 8Для autos нужно настроить Foreign Key — внешний ключ. Он будет связывать наши таблицы. Советую почитать про него подробнее; если говорить совсем просто - он ссылается на внешнюю таблицу, в нашем случае на users. Если машина принадлежит юзеру с то в поле user_id таблицы autos у нее будет 1. Так мы в нашем приложении связываем пользователей с их автомобилями. В нашей таблице autos роль внешнего ключа будет выполнять поле user_id. Оно будет ссылаться на поле id таблицы users. Ваше первое приложение на Hibernate - 9Таким образом, мы создали базу данных с двумя таблицами. Осталось понять, как управлять ей из Java-кода. Начнем мы с файла pom.xml, в котором нам необходимо подключить нужные библиотеки (на языке Maven они называются dependencies — "зависимости"). Все библиотеки хранятся в центральном репозитории Maven. Те из них, которые вы укажете в pom.xml, вы сможете использовать в проекте. Ваш pom.xml должен выглядеть так: Ваше первое приложение на Hibernate - 10Ничего сложного, как видите. Мы добавили всего 2 зависимости — для использования PostgreSQL и Hibernate.

Теперь перейдем к Java-коду. Создайте все необходимые пакеты и классы проекта. Для начала, нам понадобятся модели данных — классы User и Auto .

 package models; import javax.persistence.*; import java.util.ArrayList; import java.util.List; @Entity @Table (name = "users") public class User < @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; @Column(name = "name") private String name; //можно не указывать Column name, если оно совпадает с названием столбца в таблице private int age; @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true) private Listautos; public User() < >public User(String name, int age) < this.name = name; this.age = age; autos = new ArrayList<>(); > public void addAuto(Auto auto) < auto.setUser(this); autos.add(auto); >public void removeAuto(Auto auto) < autos.remove(auto); >public int getId() < return id; >public String getName() < return name; >public void setName(String name) < this.name = name; >public int getAge() < return age; >public void setAge(int age) < this.age = age; >public List getAutos() < return autos; >public void setAutos(List autos) < this.autos = autos; >@Override public String toString() < return "models.User package models; import javax.persistence.*; @Entity @Table(name = "autos") public class Auto < @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; @Column (name = "model") private String model; //можно не указывать Column name, если оно совпадает с названием столбца в таблице private String color; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; public Auto() < >public Auto(String model, String color) < this.model = model; this.color = color; >public int getId() < return id; >public String getModel() < return model; >public void setModel(String model) < this.model = model; >public String getColor() < return color; >public void setColor(String color) < this.color = color; >public User getUser() < return user; >public void setUser(User user) < this.user = user; >@Override public String toString() < return color + " " + model; >> 
  • Должен иметь пустой конструктор ( public или protected );
  • Не может быть вложенным, интерфейсом или enum ;
  • Не может быть final и не может содержать final -полей/свойств;
  • Должен содержать хотя бы одно @Id-поле.
  • Содержать непустые конструкторы;
  • Наследоваться и быть наследованным;
  • Содержать другие методы и реализовывать интерфейсы.
 package utils; import models.Auto; import models.User; import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; public class HibernateSessionFactoryUtil < private static SessionFactory sessionFactory; private HibernateSessionFactoryUtil() <>public static SessionFactory getSessionFactory() < if (sessionFactory == null) < try < Configuration configuration = new Configuration().configure(); configuration.addAnnotatedClass(User.class); configuration.addAnnotatedClass(Auto.class); StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()); sessionFactory = configuration.buildSessionFactory(builder.build()); >catch (Exception e) < System.out.println("Исключение!" + e); >> return sessionFactory; > > 

Ваше первое приложение на Hibernate - 11

В этом классе мы создаем новый объект конфигураций Configuration, и передаем ему те классы, которые он должен воспринимать как сущности — User и Auto . Обратите внимание на метод configuration.getProperties() . Какие еще properties? Откуда? Properties — это параметры для работы hibernate, указанные в специальном файле hibernate.cfg.xml. Hibernate.cfg.xml зачитывается здесь: new Configuration().configure(); В нем, как видите, нет ничего особенного — параметры соединения с БД, и специальный параметр show_sql. Он нужен для того, чтобы все sql-запросы, которые hibernate будет выполнять к нашей БД, выводились в консоль. Таким образом, вы будете видеть что конкретно делает Hibernate в каждый момент времени и избавитесь от эффекта "магии". Далее нам понадобится класс UserDAO . (По-хорошему, программировать нужно через интерфейсы — создать интерфейс UserDAO и отдельно его реализацию UserDAOImpl , но для сокращения объема кода я опущу это. Не делайте так в реальных проектах!). DAO (data access object) — один из наиболее распространенных паттернов проектирования, "Доступ к данным". Его смысл прост — создать в приложении слой, который отвечает только за доступ к данным, и больше ни за что. Достать данные из БД, обновить данные, удалить данные — и все. Почитайте про DAO подробнее, в работе будете пользоваться ими постоянно. Что же умеет наш класс UserDao ? Собственно, как и все DAO, он умеет только работать с данными. Найти юзера по id, обновить его данные, удалить его, вытащить из БД список всех юзеров или сохранить в БД нового юзера — вот весь его функционал.

 package dao; import models.Auto; import models.User; import org.hibernate.Session; import org.hibernate.Transaction; import utils.HibernateSessionFactoryUtil; import java.util.List; public class UserDao < public User findById(int id) < return HibernateSessionFactoryUtil.getSessionFactory().openSession().get(User.class, id); >public void save(User user) < Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession(); Transaction tx1 = session.beginTransaction(); session.save(user); tx1.commit(); session.close(); >public void update(User user) < Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession(); Transaction tx1 = session.beginTransaction(); session.update(user); tx1.commit(); session.close(); >public void delete(User user) < Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession(); Transaction tx1 = session.beginTransaction(); session.delete(user); tx1.commit(); session.close(); >public Auto findAutoById(int id) < return HibernateSessionFactoryUtil.getSessionFactory().openSession().get(Auto.class, id); >public List findAll() < Listusers = (List) HibernateSessionFactoryUtil.getSessionFactory().openSession().createQuery("From User").list(); return users; > > 

Методы UserDao похожи друг на друга. В большинстве из них мы получаем объект Session (сессия соединения с нашей БД) с помощью нашей Фабрики Сессий, создаем в рамках этой сессии одиночную транзакцию, выполняем необходимые преобразования данных, сохраняем результат транзакции в БД и закрываем сессию. Сами методы тоже, как видите, довольно просты. Именно DAO — "сердце" нашего приложения. Однако, мы не будем создавать DAO напрямую и вызывать его методы в нашем методе main() . Вся логика будет перемещена в класс UserService .

 package services; import dao.UserDao; import models.Auto; import models.User; import java.util.List; public class UserService < private UserDao usersDao = new UserDao(); public UserService() < >public User findUser(int id) < return usersDao.findById(id); >public void saveUser(User user) < usersDao.save(user); >public void deleteUser(User user) < usersDao.delete(user); >public void updateUser(User user) < usersDao.update(user); >public List findAllUsers() < return usersDao.findAll(); >public Auto findAutoById(int id) < return usersDao.findAutoById(id); >> 

Service — слой данных в приложении, отвечающий за выполнение бизнес-логики. Если ваша программа должна выполнить какую-то бизнес-логику — она делает это через сервисы. Сервис содержит внутри себя UserDao , и в своих методах вызывает методы DAO. Это может показаться вам дублированием функций (почему бы просто не вызывать методы из dao-объекта), но при большом количестве объектов и сложной логике разбиение приложения на слои дает огромные преимущества (это good practice, запомните эту информацию на будущее и почитайте про "слои приложения"). У нас-то в сервисе логика простая, а в реальных проектах методы сервисов будут содержать куда больше одной строки кода:) Теперь у нас есть все нужно для работы приложения! Давайте создадим в методе main() пользователя, машины для него, свяжем их друг с другом и сохраним в БД.

 import models.Auto; import models.User; import services.UserService; import java.sql.SQLException; public class Main < public static void main(String[] args) throws SQLException < UserService userService = new UserService(); User user = new User("Masha",26); userService.saveUser(user); Auto ferrari = new Auto("Ferrari", "red"); ferrari.setUser(user); user.addAuto(ferrari); Auto ford = new Auto("Ford", "black"); ford.setUser(user); user.addAuto(ford); userService.updateUser(user); >> 

Ваше первое приложение на Hibernate - 13

Как видите, в таблице users появилась своя запись, а в таблице autos — свои. Попробуем переименовать нашего пользователя. Очистим таблицу users и выполним код

 import models.Auto; import models.User; import services.UserService; import java.sql.SQLException; public class Main < public static void main(String[] args) throws SQLException < UserService userService = new UserService(); User user = new User("Masha",26); userService.saveUser(user); Auto ferrari = new Auto("Ferrari", "red"); user.addAuto(ferrari); Auto ford = new Auto("Ford", "black"); ford.setUser(user); user.addAuto(ford); userService.updateUser(user); user.setName("Sasha"); userService.updateUser(user); >> 

Ваше первое приложение на Hibernate - 15

Работает! А что если удалить пользователя? Очистим таблицу users (autos очистится сама) и выполним код

 import models.Auto; import models.User; import services.UserService; import java.sql.SQLException; public class Main < public static void main(String[] args) throws SQLException < UserService userService = new UserService(); User user = new User("Masha",26); userService.saveUser(user); Auto ferrari = new Auto("Ferrari", "red"); user.addAuto(ferrari); Auto ford = new Auto("Ford", "black"); ford.setUser(user); user.addAuto(ford); userService.updateUser(user); user.setName("Sasha"); userService.updateUser(user); userService.deleteUser(user); >> 

И наши таблицы абсолютно пусты (обратите внимание на консоль, туда выведутся все запросы, которые выполнил Hibernate). Вы можете "поиграться" с приложением и попробовать все его функции. Например, создайте пользователя с машинами, сохраните его в БД, посмотрите какой ID ему присвоен, и попробуйте в методе main() "вытащить" пользователя из БД по этому id и вывести в консоль список его машин. Конечно, мы увидели лишь небольшую часть функциональности Hibernate. Его возможности очень широки, и он давно является одним из промышленных стандартов Java-разработки. Если вы хотите изучить его во всех подробностях – могу рекомендовать книгу "Java Persistence API и Hibernate", обзор на которую я делал в одной из прошлых статей. Надеюсь, эта статья была полезна читателям. Если у вас будут вопросы — задавайте их в комментариях, с радостью отвечу 🙂 Также не забывайте поддержать автора в конкурсе, поставив "Нравится". А лучше — "Очень нравится" 🙂 Успехов в учебе!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *