Hibernate
Что это
Hibernate - библиотека предназначенная для решения задач объектно-реляционного отображения (ORM), самая
популярная реализация спецификации JPA. Объектно-реляционная модель описывает отношения
между программными объектами и записями в БД.
Слои взаимодействия
- Application
- Spring Data JPA(Repository) - это механизм организации репозиториев, а репозиторий - это абстракция,
лежащая на уровень выше ORM.
- Java Persistence API(JPA) — спецификация API Java EE, предоставляет возможность сохранять в удобном виде
Java-объекты в базе данных. Имеет только интерфейс. Как реализация чаще всего используется Hibernate.
- Hibernate
- JDBC
- Relational Database
Минусы
- Необходимо отслеживать проблему "N + 1"
Проблема N + 1 в JPA - возникает, когда мы генерируем запрос на получение одной сущности из базы данных,
но у данной сущности есть свои связанные сущности, которые мы тоже хотим получить и hibernate генерирует
вначале один (1) запрос к базе данных, чтобы получить интересующую нас сущность, а потом N запросов,
чтобы достать из базы данных связанные сущности.
Java Persistence Query Language (JPQL)
JPQL - платформенно-независимый объектно-ориентированный язык запросов, являющийся частью спецификации Java
Persistence API (JPA). JPQL используется для написания запросов к сущностям, хранящимся в реляционной базе
данных.
Spring конфигурация application.properties
- spring.jpa.hibernate.ddl-auto=none - чтобы Hibernate не выполнял никаких действий по модификации схемы.
К примеру для работы через Liquibase.
Аннотации для управления
- @Entity(name = "") - указывает что данный класс является сущностью(entity bean). Такой класс должен:
- Иметь конструктор по-умолчанию (пустой конструктор) public или protected.
- Не может быть final и не может содержать final-полей/свойств;
- Должен содержать хотя бы одно @Id-поле.
- Не может быть вложенным, интерфейсом или enum
- @Table(name = "") - указывает с какой именно таблицей необходимо связать (map) данный класс.
Имеет различные аттрибуты для указания имя таблицы, каталог, БД и уникальность столбцов в таблице БД.
- @Id - указывает первичный ключ (Primary Key) данного класса.
- @GeneratedValue - Эта аннотация используется вместе с аннотацией @Id и определяет такие параметры, как
strategy и generator.
- @Column - определяет к какому столбцу в таблице БД относится конкретное поле класса.
Аттрибуты: name, unique, nullable, length.
- @Access - определяет режим доступа к полям. Мы можем использовать @Access на уровне класса, поля
или метода. Мы можем даже смешивать два типа в одном классе сущностей. По умолчанию тип доступа
определяется местом, в котором находится ваш идентификатор(@ Id). Если он будет в поле -
это будет AccessType.FIELD, если он будет в геттере - это AccessType.PROPERTY. Иногда вам может
потребоваться аннотировать не поля, а свойства (например, потому что вы хотите иметь какую-то
произвольную логику в геттере или потому, что вы так предпочитаете). В такой ситуации вы должны
определить геттер и аннотировать его как AccessType.PROPERTY.
- AccessType.FIELD - обычный доступа к полю.
- AccessType.PROPERTY - для доступа к полю через get/set.
Отношения между таблицами
Дополняется CascadeType, FetchType и др.
- @OneToOne - рекомендуется EAGER.
- @OneToMany - рекомендуется LAZY.
- @ManyToOne - рекомендуется EAGER.
- @ManyToMany - рекомендуется LAZY.
CascadeType
- CascadeType.ALL - необходимо выполнять каскадно сразу все операции.
- CascadeType.PERSIST - когда выполняется метод save().
- CascadeType.MERGE
- CascadeType.REMOVE
- CascadeType.REFRESH
- CascadeType.DETACH
JPA имеет 2 типа загрузки(FetchType)
- LAZY(by default) - ORM загрузит сущность или коллекцию отложено, при первом обращении к ней из кода.
- EAGER - заставляет ORM загружать связанные сущности и коллекции сразу, вместе с корневой сущностью.
Состояние Entity:
- New
- Managed
- Removed
- Detached
Session methods
- Get() - получение данных. Если объекта нет вернет null. Вернет полностью инициализированный
объект(eager load) по этому медленнее чем Load(). Если вы не увереныы что объект есть - используйте
Get().
- Load() - получение данных. Если объекта нет вернет ObjectNotFoundException. Вернет proxy объект
(lazy load) по быстрее чем Get(). Если вы увереныы что объект есть - используйте Load().