HIBERNATE Flashcards
Что такое ORM?
ORM == Object-Relational Mapping (объектно-реляционное отображение, преобразование).
ORM (Object-Relational Mapping) - это технология, которая позволяет связывать объектно-ориентированную модель данных и реляционную базу данных и наоборот, т.е. позволяет работать с таблицами БД как с объектами.
(Преобразовывает объект в строку в таблице и наоборот)
В Java это делается с помощью рефлексии и JDBC.
Создает дополнительный слой внутри приложения, который будет отвечать за связь приложения с БД и преобразование данных БД в Объекты и наоборот.
КОД <--->
ORM ОБЪЕКТЫ <--->
БД(ТАБЛИЦЫ
ORM-фреймворки обычно позволяют создавать классы, которые соответствуют таблицам в базе данных, а также мапперы для связи между классами и таблицами. Они также предоставляют методы для выполнения CRUD-операций (Create, Read, Update, Delete) над данными.
ORM-фреймворки упрощают процесс разработки, поскольку разработчики могут использовать язык JAVA для работы с данными вместо написания SQL-запросов и последующими манипуляциями с результатами запросов.
ORM позволяет работать с объектами в памяти, что улучшает производительность приложения и позволяет избежать частых обращений к БД.
Они также позволяют скрыть детали взаимодействия с базой данных, такие как создание подключения, открытие и закрытие транзакций и т.д., что делает код более читабельным и поддерживаемым, а так же снижается вероятность ошибок, связанных с написанием SQL-запросов вручную.
Некоторые из наиболее популярных ORM-фреймворков для Java включают Hibernate, EclipseLink, MyBatis, JOOQ, Spring Data JPA и т.д.
1) ORM - технология программирования, которая связывает базы данных с объектами JAVA.
2) Тем самым получается “объектная база данных”.
3) В этом случае программист избавлен от необходимости писать конкретные sql-запросы и вручную конструировать объекты из полей таблицы БД.
Что такое JPA?
Java Persistence API - это спецификация (JSR 338 стандарт, технология) используемая для управления отображаемыми(представляемыми) POJO объектами и их хранением в реляционной базе данных.
Это спецификация Java, которая предоставляет набор интерфейсов/аннотаций для возможности сохранять в удобном виде Java объекты в БД и наоборот - извлекать информацию из БД в виде Java объектов.
Он предоставляет унифицированный интерфейс(Конкретное описание работы ORM принципов) для работы с ORM (Object-Relational Mapping) в Java-приложениях.
Он также предоставляет API для управления жизненным циклом объектов и выполнения операций CRUD (создание, чтение, обновление и удаление) в базе данных.
JPA позволяет разработчикам Java использовать объектно-ориентированный подход к работе с базами данных, что в свою очередь:
* упрощает разработку приложений
* позволяет более эффективно использовать базы данных
* снижает количество кода для работы с ними;
Сам JPA не умеет работать с объектами(не умеет ни сохранять, ни управлять объектами), JPA только определяет правила игры: как должен действовать каждый провайдер (Hibernate, EclipseLink, OJB, Torque и т.д.), реализующий стандарт JPA. Для этого JPA определяет интерфейсы, которые должны быть реализованы провайдерами. Каждый провайдер обязан реализовывать все из JPA, определяя стандартное получение, сохранение, управление объектами. Помимо этого, провайдеры могут добавлять свои личные классы и интерфейсы, расширяя функционал JPA.
Также JPA определяет правила, как должны описываться метаданные отображения и как должны работать провайдеры.
JPA определяет аннотации, которые могут использоваться для указания отображаемых объектов и связей между ними.
JPA является частью стандартной спецификации Java EE (Enterprise Edition) и может использоваться в любом Java-приложении, независимо от того, используется ли контейнер приложений Java EE или нет.
Гибкость JPA.
JAVA-код, написанный только с использованием интерфейсов и классов JPA, позволяет разработчику гибко менять одного провайдера на другого. Например, если приложение использует Hibernate как провайдера, то ничего не меняя в коде можно поменять провайдера на любой другой. Но, если мы в коде использовали интерфейсы, классы или аннотации, например, из Hibernate, то поменяв провайдера на EclipseLink, эти интерфейсы, классы или аннотации уже работать не будут.
1) JPA - это спецификация API Java Enterprise. Интерфейс предоставляет возможность сохранять в удобном виде Java-объекты в базе данных.
2) JPA реализует концепцию ORM - object-relational mapping.
3) Одна из самых популярных реализаций JPA - библиотека Hibernate.
JPA:
JPA поддерживает использование JPQL (Java Persistence Query Language) для выполнения запросов к базе данных, что упрощает написание и поддержку запросов в приложении.
JPA предоставляет возможность использования кэширования объектов для улучшения производительности приложения.
JPA позволяет использовать различные стратегии отображения объектов на таблицы базы данных, что позволяет разработчику выбрать оптимальный подход в зависимости от конкретных требований приложения.
JPA поддерживает использование аннотаций для управления отображением Java-объектов на таблицы базы данных, что делает код более читаемым и упрощает разработку приложений.
JPA позволяет использовать различные типы отношений между объектами, такие как один-к-одному, один-ко-многим и многие-ко-многим, что позволяет разработчику создавать более сложные приложения с эффективным использованием базы данных.
JPA также предоставляет возможность использования транзакций для обеспечения целостности данных при выполнении операций с базой данных.
JPQL -Java Persistence Query Language - это объектный язык запросов (запросы выполняются к объектам), используемый в Java Persistence API (JPA) для работы с базами данных.
Что такое JDBC?
JDBC (Java DataBase Connectivity)
1) Это набор API в JDK для доступа к реляционным базам данных из программы Java.
2) Эти API позволяют из Java-кода взаимодействовать с (почти) любой SQL базой данных.
3) Например, подключиться, создать таблицы, выполнять SQL-запросы и т.д.
JDBC - Java DataBase Connectivity — API для работы с реляционными (зависимыми) БД. Платформенно независимый промышленный стандарт взаимодействия Java-приложений с различными СУБД, реализованный в виде пакета java.sql, входящего в состав Java SE. Предоставляет методы для получения и обновления данных. Не зависит от конкретного типа базы. Библиотека, которая входит в стандартную библиотеу, содержит: набор классов и интерфейсов для работы с БД (для нас разработчиков api) + интерфейсы баз данных.
JDBC реализует механизмы работы подключений к базе данных, создания запросов и обработки результатов.
Наш код –> JDBC –> драйвера разработчиков БД –> БД.
JDBC has 3 entities:
-
Connection (класс). Объект которого отвечает за соединение с базой и режим работы с ней (лекция 3.1.4)
Statement (объект для оператора JDBC) используется для отправки SQL-оператора на сервер баз данных. Объект для оператора связан с объектом Connection и является объектом, обрабатывающим взаимодействие между приложением и сервером баз данных.
Можно:
что-то поменять Update statement (create, delete, insert) в базе;
что-то запросить Query statement (select) из базы;
Для разных задач есть разные виды Statement-ов: -
statement - обычный. передаем в него либо Update либо Query
PreparedStatement - возможность сделать некий шаблон запроса, подставлять в него кто-то значения и использовать его
CallableStatement - предоставляет возможность вызова хранимой процедуры, расположенной на сервере, из Java-приложения. - ResultSet. Объект с результатом запроса, который вернула база. Внутри него таблица.
Различия JPA JDBC и Hibernate?
JDBC является гораздо более низкоуровневой (и более старой) спецификацией, чем JPA. JDBC - это API-интерфейс для взаимодействия с базой данных с использованием чистого SQL - отправки запросов и получения результатов. Он не имеет понятия об объектах или иерархиях. При использовании JDBC вам необходимо преобразовать набор результатов в объекты Java.
А в JPA (который использует JDBC под капотом) вы также указываете эти детали метаданных базы данных, но с использованием аннотаций Java. Таким образом, JPA создает запросы на обновление для вас и управляет объектами, которые вы искали или создали / обновили (это также делает больше).
Hibernate одна из самых популярных открытых реализаций последней версии спецификации. То есть JPA только описывает правила и API, а Hibernate реализует эти описания.
- Hibernate удаляет множество повторяющегося кода из JDBC API, а следовательно его легче читать, писать и поддерживать.
- Hibernate поддерживает наследование, ассоциации и коллекции, что не доступно в JDBC API.
- Hibernate неявно использует управление транзакциями. Большинство запросов нельзя выполнить вне транзакции. При использовании JDBC API для управления транзакциями нужно явно использовать commit и rollback.
- JDBC API throws SQLException, которое относится к проверяемым исключениям, а значит необходимо постоянно писать множество блоков try-catch. В большинстве случаев это не нужно для каждого вызова JDBC и используется для управления транзакциями. Hibernate оборачивает исключения JDBC через непроверяемые JDBCException или HibernateException, а значит нет необходимости проверять их в коде каждый раз. Встроенная поддержка управления транзакциями в Hibernate убирает блоки try-catch.
- Hibernate Query Language (HQL) более объектно ориентированный и близкий к Java язык запросов, чем SQL в JDBC.
- Hibernate поддерживает кэширование, а запросы JDBC — нет, что может понизить производительность.
- Hibernate поддерживает аннотации JPA, а значит код является переносимым на другие ORM фреймворки, реализующие стандарт, в то время как код JDBC сильно привязан к приложению.
Что такое Hibernate?
Hibernate - это фреймворк на базе Java с открытым исходным кодом, реализующий спецификацию JPA. Hibernate полностью реализует JPA плюс добавляет функционал в виде своих классов и интерфейсов, расширяя свои возможности по работе с сущностями и БД.
Hibernate предоставляет разработчикам удобный способ работы с базами данных, позволяя им работать с базами данных через объектно-ориентированный интерфейс.
Hibernate позволяет разработчикам определить отображение между объектами Java и таблицами базы данных, а также предоставляет множество возможностей для управления этим отображением. Это включает в себя возможность определения связей между таблицами базы данных и объектами Java, определение атрибутов объектов Java и их соответствующих столбцов в таблицах базы данных, а также возможность настройки кэширования и оптимизации запросов к базе данных.
Краткий принцип работы:
JAVA APPLICATION(SAVE) --->
HIBERNATE
* Сбор данных из полей объекта
* Написание INSERT выражения для добавления новой строки в таблицу с собранными данными
JAVA APPLICATION(GET) <---
HIBERNATE
* Написание SELECT выражения для получения необходимых данных
* Создание объекта Java Класса и присвоение его полям значений, полученных из базы
Hibernate использует JDBC для работы с БД.
Основные возможности фреймворка:
1) Hibernate связывает классы Java с таблицами данных SQL.
2) Автоматическая генерация и обновление таблиц в базах данных;
3) Поскольку основные запросы к базе данных (сохранение, обновление, удаление и поиск) представлены как методы фрейморка, то значительно сокращается код, который пишется разработчиком ;
4) Обеспечивает использование SQL подобного языка (HQL — hibernate query language). Запросы HQL могут быть записаны рядом объектами данных (POJO классы подготовленные для работы с базой данных).
5) Автоматизирует генерацию SQL-запросов на “диалекте” текущей базы данных.
6) Hibernate поддерживает различные базы данных
Важные интерфейсы Hibernate:
Session extends EntityManager – обеспечивает физическое соединение между приложением и БД. Это единица работы Hibernate осуществляющая DML команды.(не является потокобезопасным объектом.)
SessionFactory – объект, который создает во время запуска приложения сессии работы с БД и сохраняет для последующего использования. Обычно создается одна sessionFactory на одну базу данных. Внутри сессий проходят транзакции. Является потокобезопасным объектом и используется всеми потоками приложения.
Transaction – представляет собой атомарную единицу работы с базой данных. Это абстракция приложения от основных JDBC-транзакций. Сессия может включать несколько транзакций.
Query – интерфейс позволяет выполнять запросы к БД. Может использовать объектный (HQL) или обычный (SQL) язык запросов.
Configuration - представляет собой объект с параметрами конфигурации, требуемыми Hibernate.
Criteria - Используется для создания и выполнения объекто-ориентированных запроса на получение объектов. Является альтернативой использованию Query. Criteria − объект, позволяющий получать из базы данных объекты по определенным критериям.
В чем заключаются преимущества использования Hibernate?
- Hibernate устраняет множество спагетти кода (повторяющегося), который постоянно преследует разработчика при работе с JDBC. Скрывает от разработчика множество кода, необходимого для управления ресурсами и позволяет сосредоточиться на бизнес логике.
- Hibernate поддерживает XML так же как и JPA аннотации, что позволяет сделать реализацию кода независимой.
- Hibernate предоставляет собственный мощный язык запросов (HQL), который похож на SQL. Стоит отметить, что HQL полностью объектно-ориентирован и понимает такие принципы, как наследование, полиморфизм и ассоциации (связи).
- Hibernate легко интегрируется с другими Java EE фреймворками, например, Spring Framework поддерживает встроенную интеграцию с Hibernate.
- Hibernate поддерживает ленивую инициализацию используя proxy объекты и выполняет запросы к базе данных только по необходимости.
- Hibernate поддерживает разные уровни cache, а следовательно может повысить производительность.
- Важно, что Hibernate может использовать чистый SQL, а значит поддерживает возможность оптимизации запросов и работы с любым сторонним вендором БД и его фичами.
Конфигурация Hibernate
Минимальная конфигурация Hibernate включает в себя несколько основных компонентов, которые необходимы для установки соединения с базой данных и запуска ORM (Object-Relational Mapping) слоя:
- Конфигурационный файл hibernate.cfg.xml: это файл конфигурации Hibernate, который содержит информацию о настройках подключения к базе данных, таких как JDBC URL, логин, пароль, диалект SQL и т.д.
Пример 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>
<property>org.hibernate.dialect.MySQL5Dialect</property>
<property>com.mysql.jdbc.Driver</property>
<property>jdbc:mysql://localhost:3306/mydb</property>
<property>root</property>
<property>password</property>
<mapping></mapping>
<mapping></mapping>
</session-factory>
</hibernate-configuration>
Configuration configuration = new Configuration();
configuration.configure(“hibernate.cfg.xml”);
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
~~~
- в Hibernate можно сконфигурировать соединение с базой данных и другие параметры без использования файла hibernate.cfg.xml. В этом случае конфигурация будет задана программно.
Например, для создания сессионной фабрики без файла hibernate.cfg.xml можно использовать следующий код:
~~~
Configuration configuration = new Configuration()
.setProperty(“hibernate.dialect”, “org.hibernate.dialect.MySQL5Dialect”)
.setProperty(“hibernate.connection.driver_class”, “com.mysql.jdbc.Driver”)
.setProperty(“hibernate.connection.url”, “jdbc:mysql://localhost:3306/mydb”)
.setProperty(“hibernate.connection.username”, “root”)
.setProperty(“hibernate.connection.password”, “password”);
.setProperty(“hibernate.show_sql”, “true”)
.setProperty(“hibernate.hbm2ddl.auto”, “update”)
.addAnnotatedClass(User.class)
.addAnnotatedClass(Order.class);
SessionFactory sessionFactory = configuration.buildSessionFactory();
~~~
В этом примере мы создаем объект Configuration и устанавливаем необходимые параметры конфигурации с помощью метода setProperty(). Затем мы добавляем аннотированные классы User и Order с помощью метода addAnnotatedClass(). Наконец, мы создаем сессионную фабрику с помощью метода buildSessionFactory().
Преимуществом программной конфигурации является возможность управления настройками Hibernate в коде и настройка их в зависимости от условий. Также это может быть полезно для тестирования и экспериментирования с различными конфигурациями без необходимости изменения файла hibernate.cfg.xml. Однако, этот способ конфигурации может быть менее удобным для конфигурации крупных проектов и может потребовать больше усилий для настройки всех параметров.
Далее:
~~~
Session session = sessionFactory.openSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
// выполнение операций с объектами
transaction.commit();
} catch (Exception e) {
if (transaction != null) {
transaction.rollback();
}
e.printStackTrace();
} finally {
session.close();
}
~~~ - Так же возможна конфигурация с помощью:
Интеграция с Spring: если проект использует Spring Framework, то для конфигурации Hibernate можно использовать специальные библиотеки, такие как Spring ORM или Spring Data. - Использование JPA: Hibernate является одной из реализаций стандарта JPA (Java Persistence API). Поэтому для конфигурации Hibernate можно использовать стандартные средства JPA, такие как файл persistence.xml.
- Использование аннотаций: Hibernate позволяет использовать аннотации для задания маппинга между классами и таблицами базы данных. В этом случае конфигурация задается непосредственно в коде с помощью аннотаций.
Для того чтобы сконфигурировать возможность подключения к базе данных с помощью аннотаций, можно использовать аннотацию @PersistenceContext вместе с аннотацией @Transactional для указания, что метод должен выполняться в контексте транзакции.
Что такое Entity?
Entity в Hibernate - это класс Java, который представляет собой объект, который может быть сохранен в базе данных.
POJO класс становится Entity классом с помощью аннотации @Entity.
Entity отображает таблицу в базе данных и содержит поля, которые соответствуют столбцам этой таблицы.
Каждый объект Entity имеет уникальный идентификатор, который используется для идентификации объекта в базе данных.(ID) Он должен реализовывать интерфейс Serializable
Entity также может иметь отношения с другими Entity, что позволяет описать связи между таблицами в базе данных.
В Hibernate Entity обычно является классом Java, который содержит поля, геттеры и сеттеры для этих полей, конструкторы и методы, которые определяют поведение объекта. Класс Entity также может иметь аннотации, которые определяют маппинг между полями класса и столбцами таблицы в базе данных.
Кроме того, Entity может иметь отношения с другими Entity, что позволяет описать связи между таблицами в базе данных. Например, одна Entity может иметь отношение “один-ко-многим” с другой Entity, что означает, что один объект этой Entity может иметь несколько связанных объектов другой Entity.
Эти поля или свойства используют аннотации объектно-реляционного сопоставления (маппинга) для сопоставления сущностей и отношений между ними с реляционными данными в хранилище данных. Примеры аннотаций: @OneToOne, @OneToMany, @ManyToOne, @ManyToMany.
Hibernate использует Entity для выполнения операций CRUD (создание, чтение, обновление и удаление) в базе данных.
В целом, Entity в Hibernate представляет собой объект, который может быть сохранен в базе данных и имеет поля, которые соответствуют столбцам таблицы в базе данных. Он также может иметь отношения с другими Entity и используется для выполнения операций CRUD в базе данных.
Каким условиям должен удовлетворять класс чтобы являться Entity?
Требования к Entity классу в JPA
1. Entity класс должен быть помечен аннотацией @Entity или описан в XML файле конфигурации JPA.
2. Entity класс должен содержать public или protected конструктор без аргументов (он также может иметь конструкторы с аргументами).
3. Entity класс должен быть классом верхнего уровня (top-level class).
4. Перечисление [enum] или интерфейс [interface] не могут быть определены как сущность [Entity].
5. Entity класс не может быть финальным классом (final class). Entity класс не может содержать финальные поля или методы, если они участвуют в маппинге (persistent final methods or persistent final instance variables).
6. Если объект Entity класса будет передаваться по значению как отделённый от контекста персистентности объект (detached object), например через удаленный интерфейс (through a remote interface), то он также должен реализовывать интерфейс Serializable (чтобы объекты которые достаются из базы могли сохраняться в кэше).
7. Как обычный так и абстрактный класс может быть Entity. Entities могут наследоваться как от не Entity классов, так и от Entity классов. А не Entity классы могут наследоваться от Entity классов.
8. Поля Entity класса должны быть объявлены private, protected или package-private, быть напрямую доступными только методам самого Entity класса и не должны быть напрямую доступны другим классам, использующим этот Entity. Другие классы должны обращаться только к специальным методам Entity класса, предоставляющим доступ к этим полям (getter/setter-методам или другим методам бизнес-логики в Entity классе).
9. Entity класс должен содержать первичный ключ, то есть атрибут или группу атрибутов, которые уникально определяют запись этого Entity класса в базе данных.
10. Должен быть POJO.
Требования к Entity классу в Hibernate
Hibernate не так строг в своих требованиях. Вот отличия от требований JPA:
- Класс сущности должен иметь конструктор без аргументов, который может быть не только public или protected, но и package visibility (default).
- Класс сущности не обязательно должен быть классом верхнего уровня.
- Технически Hibernate может сохранять финальные классы или классы с финальными методами (getter / setter). Однако, как правило, это не очень хорошая идея, так как это лишит Hibernate возможности генерировать прокси для отложенной загрузки сущности.
- Hibernate не запрещает разработчику приложения открывать прямой доступ к переменным экземпляра и ссылаться на них извне класса сущности.
Что такое Session? Какие функции он выполняет?
Session – однопоточный короткоживущий объект, который предоставляет связь между объектами приложения и базой данных. Он оборачивает JDBC java.sql.Connection и работает как фабрика для org.hibernate.Transaction.
Session выполняет следующие функции:
- Управление жизненным циклом объектов: Session отслеживает состояние объектов и обеспечивает их сохранение в базе данных при необходимости.
- Выполнение запросов: Session позволяет выполнять запросы к базе данных с помощью языка HQL (Hibernate Query Language).
- Кэширование данных: Session кэширует данные, чтобы ускорить доступ к ним и уменьшить количество запросов к базе данных.
- Управление транзакциями: Session обеспечивает управление транзакциями базы данных и гарантирует целостность данных при выполнении операций.
- Работа с отношениями между объектами: Session позволяет работать с отношениями между объектами, такими как связи один-ко-многим и многие-ко-многим.
Экземпляр Session является интерфейсом между кодом в java приложении и hibernate framework и предоставляет методы для операций CRUD. Расширяет интерфейс EntityManager
Когда мы работаем с Hibernate, все операции с объектами выполняются в контексте сессии (Session). Изменения, которые мы вносим в объекты в рамках сессии, могут быть отложены и не записаны в базу данных до тех пор, пока мы явно не вызовем метод session.flush().
Этот метод гарантирует, что все изменения, которые были произведены в рамках текущей транзакции, будут сохранены в базе данных. Если во время выполнения session.flush() возникнет какая-либо ошибка, то транзакция будет откатана и изменения будут отменены.
что делает метод flush() в Hibernate
Метод flush() в Hibernate принудительно сбрасывает все изменения, ожидающие выполнения в текущей сессии, в базу данных. Это означает, что все операции записи, обновления или удаления объектов, которые были сделаны во время текущей транзакции, будут выполнены в базе данных.
Когда вы вызываете flush(), Hibernate проверяет, есть ли у объектов изменения, которые нужно сохранить в базе данных, и если такие изменения есть, они будут отправлены в базу данных немедленно. Таким образом, если вы вызываете flush(), то не нужно ждать завершения транзакции, чтобы увидеть изменения в базе данных.
Важно отметить, что вызов метода flush() не завершает текущую транзакцию и не коммитит изменения в базу данных. Вместо этого метод flush() только записывает все изменения в текущей сессии в базу данных, чтобы они были доступны для других сессий. Flush() также может вызывать события, такие как проверка ограничений на целостность данных и генерация исключений, если какие-либо ограничения были нарушены.
После вызова метода flush() вы можете продолжить работу с объектами в текущей сессии, и ваши изменения будут отражены в базе данных. Однако, если вы хотите завершить транзакцию и сохранить все изменения в базе данных, вам нужно вызвать метод commit() на объекте Transaction.
Обычно вызов flush() не требуется, так как Hibernate автоматически сбрасывает изменения в базу данных при необходимости. Однако, если вы хотите увидеть изменения в базе данных немедленно или нужно выполнить операции записи или обновления в базе данных перед выполнением других действий, то вызов flush() может быть полезным.
Что такое Transaction ? Какие функции он выполняет?
Transaction hibernate - это технология, которая используется для управления транзакциями в приложении Hibernate.
Transaction в Hibernate представляет собой логическую единицу работы с базой данных, которая может быть выполнена как единое целое. Транзакция начинается вызовом метода transaction.begin() и заканчивается вызовом метода commit() или rollback(). Транзакция обычно используется для обеспечения целостности данных, при которой все изменения в базе данных происходят в рамках одной транзакции, что гарантирует, что либо все изменения будут сохранены в базе данных, либо ни одного из них.
Transaction в Hibernate выполняет следующие функции:
- Обеспечивает атомарность, целостность и постоянство изменений в базе данных, выполняемых в рамках транзакции.
- Позволяет группировать несколько операций в одну транзакцию, чтобы обеспечить ее атомарность и целостность.
- Определяет границы изменений, которые должны быть зафиксированы в базе данных или отменены, если произошла ошибка.
- Управляет блокировками, чтобы предотвратить конфликты при одновременном доступе к данным из нескольких потоков.
Transaction использует объект Session для управления транзакциями в Hibernate. Каждая транзакция должна быть ассоциирована с конкретной сессией, которая предоставляет доступ к объектам базы данных.
Session session = sessionFactory.openSession(); Transaction tx = null; try { tx = session.beginTransaction(); // выполнение операций с объектами в базе данных tx.commit(); // зафиксировать изменения } catch (Exception e) { if (tx!=null) tx.rollback(); // откатить изменения в случае ошибки e.printStackTrace(); } finally { session.close(); }
Фиксация транзакции - это процесс сохранения изменений в базе данных после успешного выполнения всех операций, связанных с транзакцией. Transaction Hibernate автоматически фиксирует транзакцию после ее успешного завершения.
Что такое SessionFactory? Какие функции он выполняет?
SessionFactory в Hibernate является фабрикой сессий, которая создает объекты Session для работы с базой данных. Он является ключевым компонентом Hibernate и обеспечивает управление жизненным циклом сессий.
SessionFactory отвечает за считывание параметров конфигурации Hibernate и подключение к базе данных.
Обычно в приложении имеется только один экземпляр SessionFactory и потоки, обслуживающие клиентские запросы, получают экземпляры session с помощью объекта SessionFactory. Внутреннее состояние SessionFactory неизменно (immutable). Internal state (внутреннее состояние) включает в себя все метаданные об Object/ Relational Mapping и задается при создании SessionFactory.
SessionFactory выполняет следующие функции:
1. Создание объектов Session: SessionFactory создает новые объекты Session для каждого запроса к базе данных.
2. Управление соединениями: SessionFactory управляет соединениями с базой данных и обеспечивает их оптимальное использование.
3. Кэширование метаданных: SessionFactory кэширует метаданные, такие как информация о таблицах и отображениях объектов, что позволяет ускорить доступ к данным.
4. Поддержка многопоточности: SessionFactory обеспечивает поддержку многопоточности и безопасность при работе с базой данных.
5. Настройка Hibernate: SessionFactory позволяет настраивать различные параметры Hibernate, такие как настройки соединения с базой данных, параметры кэширования и т.д.
6. Управление транзакциями: SessionFactory обеспечивает управление транзакциями базы данных и гарантирует целостность данных при выполнении операций.
Т.к. объект SessionFactory immutable (неизменяемый), то , он потокобезопасный. Множество потоков может обращаться к одному объекту одновременно.
Что такое EntityManager? Какие функции он выполняет?
EntityManager интерфейс JPA, который описывает API для всех основных операций над Entity, а также для получения данных и других сущностей JPA.
EntityManager - это интерфейс в рамках технологии Java Persistence API (JPA), который предоставляет API для работы с объектами, хранящимися в базе данных.
Это интерфейс JPA, используемый для взаимодействия с Persistence context.
Persistence context — это среда в которой экземпляры Entity синхронизируются с аналогичными Entity в базе данных. Persistence context является своего рода кэшем данных в рамках транзакции - это и есть кэш первого уровня. Внутри Persistence context происходит управление экземплярами Entity и их жизненным циклом.
Persistence context - это механизм в JPA, который отслеживает изменения объектов в базе данных и управляет их жизненным циклом. Он помогает сохранять данные в базе данных и управлять изменениями в рамках транзакций при помощи EntityManager. Когда мы создаем новый объект или получаем его из базы данных, он добавляется в persistence context и все изменения в объектах автоматически сохраняются в базе данных при завершении транзакции.
EntityManager автоматически сохраняет в БД все изменения, сделанные в его персистентном контексте, в момент коммита транзакции, либо при явном вызове метода flush().
Один или несколько EntityManager образуют или могут образовать persistence context.
Он предоставляет API для выполнения операций с базой данных, таких как создание, чтение, обновление и удаление объектов.
EntityManager описывает API для всех основных операций над Entity, а также для получения данных и других сущностей JPA. По сути - главный API для работы с JPA.
Если проводить аналогию с обычным JDBC, то EntityManagerFactory будет аналогом DataSource, а EntityManager аналогом Connection.
Основные функции EntityManager:
1) Операции над Entity: persist (добавление Entity), merge (обновление), remove (удаления), refresh (обновление данных), detach (удаление из управление JPA), lock (блокирование Entity от изменений в других thread),
2) Получение данных: find (поиск и получение Entity), createQuery, createNamedQuery, createNativeQuery, contains, createNamedStoredProcedureQuery, createStoredProcedureQuery
3) Получение других сущностей JPA: getTransaction, getEntityManagerFactory, getCriteriaBuilder, getMetamodel, getDelegate
4) Работа с EntityGraph: createEntityGraph, getEntityGraph
5) Общие операции над EntityManager или всеми Entities: close, clear, isOpen, getProperties, setProperty.
6) Выполнение запросов: EntityManager позволяет выполнять запросы к базе данных с помощью языка JPQL (Java Persistence Query Language).
7) Управление транзакциями: EntityManager обеспечивает управление транзакциями базы данных и гарантирует целостность данных при выполнении операций.
Что такое Persistence context
Persistence context он же first level Cash
PC является проекцией на нашу текущую БД а точнее на ее состояние в данный момент времени.
У каждой Session есть свой Persistence context
Persistence context - это контекст, в котором находятся все объекты, которые были получены из базы данных или созданы при помощи EntityManager. Он является частью EntityManager и предоставляет механизм отслеживания изменений объектов и обеспечивает управление жизненным циклом сущностей и их сохранением в базе данных.
Persistence context (контекст сохранения) - это среда, в которой происходит взаимодействие между объектами Java и базой данных в рамках Java Persistence API (JPA). Контекст сохранения представляет собой набор управляемых объектов сущностей, которые находятся в состоянии persistent (постоянном), то есть связанных с базой данных и готовых к сохранению или обновлению. Контекст сохранения отслеживает изменения объектов и автоматически синхронизирует их с базой данных при вызове метода commit() или при завершении транзакции. Контекст сохранения также обеспечивает кэширование объектов и оптимизацию запросов к базе данных.
очистить кэш можно используя методы:
* evict(user); - удаляем объект из кэша
* clear(); - очистка мапы
* close(); - закрыть сессию
Persistence context:
* Набор управляемых объектов сущностей, которые были получены из базы данных или созданы в рамках приложения.
* Кэш первого уровня, который содержит копии объектов сущностей, полученных из базы данных. Это позволяет избежать повторных запросов к базе данных при повторном доступе к объекту.
* Кэш второго уровня, который содержит копии объектов сущностей, полученных из базы данных. Это позволяет избежать повторных запросов к базе данных при повторном доступе к объекту на других уровнях приложения.
Например, если мы создадим новый объект с помощью метода persist(), он будет добавлен в persistence context. В дальнейшем, любые изменения, внесенные в этот объект, будут отслеживаться EntityManager и автоматически сохраняться в базе данных при завершении транзакции.
Кроме того, если мы получим объект из базы данных при помощи метода find(), он также будет добавлен в persistence context. При последующих вызовах методов EntityManager для этого объекта будет использован именно этот экземпляр из persistence context.
Примеры использования Persistence context:
- Создание нового объекта и его добавление в persistence context:
EntityManager em = entityManagerFactory.createEntityManager(); em.getTransaction().begin(); Employee employee = new Employee(); employee.setName("John"); em.persist(employee); em.getTransaction().commit(); em.close();
В этом примере мы создаем нового сотрудника и добавляем его в persistence context при помощи метода persist(). Затем при завершении транзакции все изменения будут автоматически сохранены в базе данных.
- Изменение объекта, полученного из базы данных:
EntityManager em = entityManagerFactory.createEntityManager(); em.getTransaction().begin(); Employee employee = em.find(Employee.class, 1L); employee.setName("Jane"); em.getTransaction().commit(); em.close();
В этом примере мы получаем объект Employee из базы данных при помощи метода find() и изменяем его имя. Так как объект находится в persistence context, изменения будут автоматически сохранены в базе данных при завершении транзакции.
Схема работы HIbernate
Конечная цель Hibernate - сохранение данных в базе данных, и Session является основным объектом для работы с Hibernate. Он предоставляет API для выполнения CRUD (Create, Read, Update, Delete) операций с базой данных.
Ниже приведен пример использования SessionFactory и Transaction в Hibernate:
// Инициализация конфигурации Hibernate Configuration configuration = new Configuration(); configuration.configure("hibernate.cfg.xml"); // Создание объекта SessionFactory из конфигурации Hibernate SessionFactory sessionFactory = configuration.buildSessionFactory(); // Получение объекта Session из SessionFactory Session session = sessionFactory.openSession(); // Создание объекта транзакции Transaction transaction = session.beginTransaction(); try { // Выполнение операций сохранения, чтения, обновления или удаления объектов // ... // Закрываем транзакцию transaction.commit(); } catch (Exception e) { // Откатываем транзакцию в случае возникновения ошибки transaction.rollback(); } finally { // Закрываем объект Session session.close(); }
В этом примере мы создаем конфигурацию Hibernate, инициализируем ее из файла hibernate.cfg.xml и создаем объект SessionFactory. Затем мы открываем объект Session из SessionFactory и создаем транзакцию для выполнения операций с базой данных. Внутри транзакции мы можем выполнить операции с объектами, которые находятся в управляемом состоянии (например, сохранение, загрузка, обновление, удаление). После выполнения операций мы фиксируем изменения в базе данных с помощью tx.commit(). Если происходит исключение, мы откатываем транзакцию и закрываем сессию.
как между собой взаимодействуют entitymanager , persistence context, Session, session factory и transaction в hibernate?
EntityManager и Session - это два инструмента, которые используются для работы с базами данных в Hibernate. EntityManager является частью Java Persistence API (JPA), а Session - частью Hibernate API.
Persistence context и Session - это контексты, в которых находятся все объекты, которые были получены из базы данных или созданы. Они предоставляют механизм отслеживания изменений объектов и управления их жизненным циклом. EntityManager и Session обеспечивают управление этими контекстами и объектами.
EntityManager и Persistence Context:
EntityManager является аналогом Session в JPA. Persistence Context - это контекст персистентности, который управляет объектами, хранящимися в базе данных. Каждый EntityManager имеет свой Persistence Context, который содержит все объекты, загруженные из базы данных и управляемые этим EntityManager.
Session и EntityManager являются интерфейсами, которые предоставляют способы управления состоянием объектов, связи с базой данных и выполнения операций, таких как сохранение, загрузка, обновление и удаление.
SessionFactory является фабрикой сессий (Session). Сессия представляет собой механизм для выполнения операций с базой данных в рамках определенной транзакции. При создании сессии, Hibernate создает новый Persistence Context для этой сессии. Persistence Context - это контейнер, который содержит все объекты, загруженные из базы данных и управляемые этой сессией.
Transaction - это транзакция, которая используется для управления изменениями в базе данных. Она обеспечивает контроль над целостностью данных, позволяет откатывать изменения в базе данных при необходимости и устраняет проблемы с параллельным доступом к данным.
Транзакция - это механизм для группировки нескольких операций в базе данных в одну атомарную единицу работы. В Hibernate транзакции начинаются и заканчиваются с помощью методов begin() и commit() соответственно.
Transaction взаимодействует с EntityManager/Session для контроля транзакций.
Таким образом, взаимодействие между EntityManager, Persistence context, Session, Session Factory и Transaction в Hibernate осуществляется следующим образом:
- Session Factory используется для создания сессий (Session).
- Session используется для выполнения операций над объектами, хранящимися в базе данных.
- EntityManager и Persistence Context управляют жизненным циклом объектов и обеспечивают автоматическое сохранение изменений в базе данных.
- Transaction используется для управления транзакцией и обеспечения контроля над целостностью данных.
В целом, все эти компоненты работают вместе для обеспечения эффективной работы с базами данных в Hibernate.
Может ли абстрактный класс быть Entity?
В спецификации JPA в пункте 2.1 The Entity Class есть строка: “И абстрактные, и конкретные классы могут быть сущностями”. То есть, ответ — да, абстрактный класс может быть сущностью и может быть аннотирован с помощью @Entity.
Может, при этом он сохраняет все свойства Entity, за исключением того, что его нельзя непосредственно инициализировать.
Может ли Entity класс наследоваться от не Entity классов (non-entity classes)?
Да, сущности могут наследоваться от не Entity классов, которые, в свою очередь, могут быть как абстрактными, так и обычными. Состояние (поля) не Entity суперкласса не является персистентным, то есть не хранится в БД и не обрабатывается провайдером (Hibernate), поэтому любое такое состояние (поля), унаследованное Entity классом, также не будет отображаться в БД.
Да, Entity класс может наследоваться от non-entity классов, так как наследование не влияет на то, удовлетворяет ли класс условиям Entity. Главное, чтобы сам класс удовлетворял всем условиям Entity.
Может ли Entity класс наследоваться от других Entity классов?
Да, Entity класс может наследоваться от других Entity классов.
Может ли не Entity класс наследоваться от Entity класса?
Да, может.
Что такое встраиваемый (Embeddable) класс?
Embeddable-класс – это класс, который не используется сам по себе, а является частью одного или нескольких entity-классов.
Во время выполнения каждый встраиваемый класс принадлежит только одному объекту entity-класса и не может быть использован для передачи данных между объектами entity-классов (то есть такой класс не является общей структурой данных для разных объектов).
Встраиваемый класс помечается аннотацией @Embeddable.
Embeddable-класс может содержать другой встраиваемый класс. Entity класс могут содержать как одиночные встраиваемые классы, так и коллекции таких классов.
Например, если у нас есть класс “Адрес”, который содержит в себе поля “город”, “улица” и “зипкод”, то мы можем создать встраиваемый класс “Адрес”, который будет содержать эти же поля. Этот класс может быть использован в других классах, например, в классе “Пользователь”, который будет содержать в себе информацию о пользователе и его адресе.
@Embeddable public class Address { @Column(name = "street") private String street; @Column(name = "city") private String city; @Column(name = "zip_code") private String zipCode; // геттеры и сеттеры // ... }
@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "name") private String name; @Embedded private Address address; // геттеры и сеттеры // ... }
В этом примере класс Address является встраиваемым классом, содержащим три атрибута: street, city и zipCode. Этот класс может быть использован как атрибут в других сущностях для представления адреса объекта.
Особенности встраиваемых классов
- все поля встраиваемого класса, даже коллекции, станут полями класса, в который происходит встраивание;
- встраиваемые классы могут быть встроены в одну и ту же сущность несколько раз, нужно только поменять имена полей;
- экземпляры встраиваемых классов, в отличие от экземпляров сущностей, не имеют собственного персистентного состояния, вместо этого они существуют только как часть состояния объекта, которому они принадлежат;
- встраиваемые классы могут использовать в качестве полей:
Какие требования JPA
устанавливает к встраиваемым (Embeddable) классам?
Требования к встраиваемым классам:
* Должны соответствовать требованиям для сущностей (раздел 2.1 Java Persistence API), за исключением того, что у встраиваемых классов не ставится аннотация @Entity и может отсутствовать первичный ключ (@Id).
* Должны быть аннотированы @Embeddable.
* Класс, содержащий встраиваемый класс, должен содержать поле с типом этого класса.
* Встраиваемый класс не может иметь своего собственного идентификатора, он наследует идентификатор из класса, в котором он используется.
Что такое Mapped Superclass?
Mapped Superclass это класс от которого наследуются Entity, он может содержать аннотации JPA, однако сам такой класс не является Entity, ему не обязательно выполнять все требования установленные для Entity (например, он может не содержать первичного ключа). Такой класс не может использоваться в операциях EntityManager или Query. Такой класс должен быть отмечен аннотацией MappedSuperclass или соответственно описан в xml файле.
В контексте фреймворка JPA (Java Persistence API), Mapped Superclass - это способ повторного использования общих полей и методов среди нескольких сущностей в рамках иерархии наследования. Он используется для выноса общих полей и методов из сущностей в отдельный класс, который не является сущностью, но может быть унаследован другими сущностями.
Использование Mapped Superclass позволяет сократить дублирование кода при определении сущностей и упростить обслуживание при изменении общих полей или методов.
Особенности:
- Должен быть помечен аннотацией @MappedSuperclass или описан в xml файле. - Не может использоваться в операциях EntityManager или Query, вместо этого нужно использовать классы-наследники.
- Не может состоять в отношениях с другими сущностями (в сущности нельзя создать поле с типом сопоставленного суперкласса).
- Может быть абстрактным.
- Не имеет своей таблицы в БД.
Для того, чтобы использовать Mapped Superclass, достаточно унаследовать его в классах-потомках:
~~~
@MappedSuperclass
public class Employee {
@Id
@GeneratedValue
private long id;
private String name;
………….
}
@Entity
@Table(name = “FULL_TIME_EMP”)
public class FullTimeEmployee extends Employee {
private int salary;
………….
}
@Entity
@Table(name = “PART_TIME_EMP”)
public class PartTimeEmployee extends Employee {
private int hourlyRate;
………….
}
~~~
В указанном примере кода в БД будут таблицы FULLTIMEEMPLOYEE и PARTTIMEEMPLOYEE, но таблицы EMPLOYEE не будет:
Mapped Superclass vs. Embeddable class
Mapped Superclass — это класс сущности, который предоставляет информацию о сопоставлении для своих подклассов, но не может быть создан сам по себе.
Embeddable class — это класс, не являющийся сущностью, который представляет собой набор свойств, которые являются общими для нескольких классов сущностей и могут быть внедрены в таблицы или столбцы этих сущностей.
Сходства:
- не являются сущностями и могут иметь все аннотации, кроме @Entity;
- не имеют своих таблиц в БД;
- не могут использоваться в операциях EntityManager или Query.
Различия: - MappedSuperclass - наследование, Embeddable class- композиция (экземпляр «части» может входить только в одно целое (или никуда не входить));
- поля из Mapped Superclass могут быть у сущности в одном экземпляре, полей из Embeddable class может быть сколько угодно (встроив в сущность Embeddable class несколько раз и поменяв имена полей);
- в сущности нельзя создать поле с типом сопоставленного суперкласса, а с Embeddable можно и нужно.
Какие три типы стратегии наследования мапинга (Inheritance Mapping Strategies) описаны в JPA?
Стратегии наследования нужны для того, чтобы дать понять провайдеру (Hibernate) как ему отображать в БД сущности-наследники. Для этого нам нужно декорировать родительский класс аннотацией @Inheritance и указать один из типов отображения: SINGLE_TABLE, TABLE_PER_CLASS, JOINED.
SINGLE_TABLE. Одна таблица на всю иерархию классов.
TABLE_PER_CLASS. Таблица для каждого конкретного класса сущностей.
JOINED. Стратегия «соединения», при которой поля или свойства, специфичные для подклассов, отображаются в таблицах этих подклассов, а поля или свойства родительского класса отображаются в таблице родительского класса.
@Inheritance(strategy = InheritanceType.JOINED) @Entity @DiscriminatorColumn(name = "EMP_TYPE") //определение типа наследника
Одна таблица на всю иерархию классов (SINGLE TABLE)
Является стратегией по умолчанию и используется, когда аннотация @Inheritance не указана в родительском классе или когда она указана без конкретной стратегии. все enity, со всеми наследниками записываются в одну таблицу, для идентификации типа entity определяется специальная колонка “discriminator column”.
Существует проблема денормализации таблицы, так как все данные хранятся в одной таблице.
Например, если есть entity Animals c классами-потомками Cats и Dogs, при такой стратегии все entity записываются в таблицу Animals, но при это имеют дополнительную колонку animalType в которую соответственно пишется значение «cat» или «dog».Минусом является то что в общей таблице, будут созданы все поля уникальные для каждого из классов-потомков, которые будет пусты для всех других классов-потомков. Например, в таблице animals окажется и скорость лазанья по дереву от cats и может ли пес приносить тапки от dogs, которые будут всегда иметь null для dog и cat соответственно.
объединяющая стратегия (joined subclass strategy)в этой стратегии каждый класс enity сохраняет данные в свою таблицу, но только уникальные колонки (не унаследованные от классов-предков) и первичный ключ, а все унаследованные колонки записываются в таблицы класса-предка, дополнительно устанавливается связь (relationships) между этими таблицами,
например в случае классов Animals (см.выше), будут три таблицы animals, cats, dogs, причем в cats будет записана только ключ и скорость лазанья, в dogs — ключ и умеет ли пес приносить палку, а в animals все остальные данные cats и dogs c ссылкой на соответствующие таблицы. Минусом тут являются потери производительности от объединения таблиц (join) для любых операций.
одна таблица для каждого класса (table per concrete class strategy)
каждый отдельный класс-наследник имеет свою таблицу в которой присутствуют в т.ч. унаследованные поля. ТАблица предка не создаётся.
каждый отдельный класс-наследник имеет свою таблицу в которой присутствуют в т.ч. унаследованные поля. ТАблица предка не создаётся.
Минусы
- плохая поддержка полиморфизмаи
- для выборки всех классов иерархии потребуются большое количество отдельных sql-запросов или использование UNION-запроса.
- Не можем использвать стратегию генерации ключа “IDENTITY”
- Снижение производительности, из за большого количества joino`в
Пример реализации стратегии
@Entity @Table(name = "employees") @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name = "employee_type") public abstract class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; // общие поля для всех сущностей // геттеры и сеттеры } @Entity @DiscriminatorValue("manager") public class Manager extends Employee { private String department; // поля для сущности Manager // геттеры и сеттеры } @Entity @DiscriminatorValue("developer") public class Developer extends Employee { private String programmingLanguage; // поля для сущности Developer // геттеры и сеттеры }
В этом примере сущности Manager и Developer наследуются от абстрактного класса Employee с помощью стратегии Single Table. В таблице employees хранятся все поля всех сущностей, а для отличия объектов друг от друга используется столбец employee_type. С помощью аннотации @DiscriminatorValue указывается значение этого столбца для каждой сущности.
Как мапятся Enumы?
- @Enumerated(EnumType.STRING) означает, что в базе будут храниться имена Enum. Всё сломается при переименовании Enum
- **@Enumerated(EnumType.ORDINAL) **– в базе будут храниться порядковые номера Enum. Всё сломается при добавленнии или изменении порядка значений. Используется по-умолчанию.
- Можно смапить enum в БД и обратно в методах с аннотациями **@PostLoad и @PrePersist. @EntityListener **над классом Entity, где указать класс, в котором создать два метода, помеченных этими аннотациями. Идея в том, чтобы в сущности иметь не только поле с Enum, но и вспомогательное поле. Поле с Enum аннотируем @Transient, а в БД будет храниться значение из вспомогательного поля. Нельзя иметь 2 Enum с одинаковыми атрибутами. и использовать JPQL
- В JPA с версии 2.1 можно использовать Converter для конвертации Enum’а в некое его значение для сохранения в БД и получения из БД. Нужно лишь создать новый класс, который реализует javax.persistence.AttributeConverter и переписать 2 метода
Как мапятся даты (до Java 8 и после)?
До Java 8 даты могли быть маппированы в базу данных с помощью классов java.util.Date или java.sql.Date. или java.util.Calendar
Для этого в JPA используется аннотация @Temporal, которая указывает, какой тип данных должен быть использован при сохранении даты в базе данных.
После Java 8 появился новый пакет java.time, который содержит новые классы для работы с датами и временем. В JPA 2.2 была добавлена поддержка этих классов с помощью аннотации @Convert, которая позволяет указать конвертер, который будет использоваться для преобразования значений между Java-кодом и базой данных.
До Java 8 даты мапятся с помощью класса java.util.Date или его наследников (например, java.sql.Date или java.sql.Timestamp). В Hibernate используются аннотации @Temporal и @Column для указания типа данных и формата хранения даты в базе данных.
Пример маппинга даты до Java 8:
@Entity public class Order { @Id private Long id; @Temporal(TemporalType.TIMESTAMP) @Column(name = "order_date") private Date orderDate; }
После Java 8 для маппинга дат используется новый класс java.time.LocalDate, java.time.LocalTime и java.time.LocalDateTime. В Hibernate также используются аннотации @Temporal и @Column для указания типа данных и формата хранения даты в базе данных.
Пример маппинга даты после Java 8:
@Entity public class Order { @Id private Long id; @Column(name = "order_date") private LocalDateTime orderDate; }
Как “смапить” коллекцию примитивов?
Для маппинга коллекции примитивных типов данных в Hibernate следует использовать аннотацию @ElementCollection.
Если у сущности коллекция базовых или встраиваемых (embeddable) типов, то для этих случаев в JPA имеется специальная аннотация @ElementCollection, которая указывается в классе сущности над полем коллекции. Тогда все записи коллекции хранятся в отдельной таблице.
При добавлении новой строки в коллекцию она полностью очищается и заполняется заново, так как у элементов нет id.
Если нужно сохранять порядок элементов в коллекции, то можно использовать аннотацию @OrderColumn:
~~~
@ElementCollection
@OrderColumn(name = “position”)
private List<Integer> myIntegers = new ArrayList<>();
~~~</Integer>
Если нужно использовать другое имя таблицы для коллекции, то можно использовать аннотацию @CollectionTable:
~~~
@ElementCollection
@CollectionTable(name = “my_integers_table”)
private List<Integer> myIntegers = new ArrayList<>();
~~~
```
@Entity
public class User {
@Id
@GeneratedValue
private Long id;</Integer>
private String name; @ElementCollection private Set<String> emails; // геттеры и сеттеры } ~~~ В этом примере поле emails отображается с помощью аннотации @ElementCollection, что означает, что это коллекция элементов, которые не являются сущностями. Hibernate автоматически создаст таблицу User_emails, которая будет содержать колонки User_id и emails, которые будут соответствовать полю id сущности User и элементам коллекции emails соответственно.
Какие есть виды связей в Hibernate?
@OneToOne -когда один экземпляр Entity может быть связан не больше чем с одним экземпляром другого Entity.
@OneToMany - когда один экземпляр Entity может быть связан с несколькими экземплярами других Entity.
@ManyToOne - обратная связь для OneToMany. Несколько экземпляров Entity могут быть связаны с одним экземпляром другого Entity.
@ManyToMany - экземпляры Entity могут быть связаны с несколькими экземплярами друг друга.
Кроме того, в Hibernate также существует возможность использования дополнительных атрибутов для связей, таких как @JoinColumn, @JoinTable и @MappedBy. Они позволяют настроить более сложные отношения между сущностями.
Каждую группу можно дополнительно разделить на
1. Bidirectional с использованием @MappedBy * на стороне, где указывается @OneToMany
2. Unidirectional. без использования @mappedBy (Hibernate создаёт смежную таблицу, в которой связывает значениях таблиц. Что ухудшает производительность.)
Bidirectional — ссылка на связь устанавливается у всех Entity, то есть в случае OneToOne A-B в Entity A есть ссылка на Entity B, в Entity B есть ссылка на Entity A. Entity A считается владельцем этой связи (это важно для случаев каскадного удаления данных, тогда при удалении A также будет удалено B, но не наоборот).
Undirectional- ссылка на связь устанавливается только с одной стороны, то есть в случае OneToOne A-B только у Entity A будет ссылка на Entity B, у Entity B ссылки на A не будет.