Similar presentations:
Hibernate. Aston
1.
Hibernateastondevs.ru
2.
ORM — технология программирования, которая связываетбазы данных с концепциями объектно-ориентированных
языков программирования, создавая «виртуальную
объектную базу данных». Если упростить, то ORM это связь
Java объектов и записей в БД:
3.
Плюсы:1.
2.
3.
4.
5.
ORM упрощает жизнь разработчиков и уменьшает время написания кода.
При использовании ORM мы “говорим” с бд на объектном языке.
ORM среда не зависимая (можем менять СУБД как перчатки).
ORM реализует поддерживает ассоциации.
ORM поддерживает наследование, а также полиморфные запросы.
Минусы:
1.
2.
Страдает производительность.
Если реализуем нужны не простенькие CRUD операции, необходимо знать что происходит.
4. ORM, JPA и Hibernate
ORM — это по сути концепция о том, что Java объект можнопредставить как данные в БД (и наоборот). Она нашла воплощение в
виде спецификации JPA — Java Persistence API.
JPA (Java Persistence API) это спецификация Java EE и Java SE,
описывающая систему управления сохранением java объектов в
таблицы реляционных баз данных в удобном виде
Hibernate - ORM фреймворк, который является реализацией
спецификации JPA
5. JPA архитектура
• EntityManagerFactory – создает и управляет EntityManager• EntityManager – предоставляет API для persist’инга
сущностей (Entity)
• Entity – java объекты, которые мы храним в БД.
• EntityTransaction – позволяет управлять транзакциями,
связан 1 к 1 с EntityManager.
• Query – интефейс используемый для контроля выполнения
запросов.
• Persistence – позволяет получить доступ к
EntityManagerFactory (использовать его вам не нужно)
6. Hibernate архитектура
7.
8.
• Session можно рассматривать, как аналог Connection из JDBC, т.к. сессия является физическимсоединением с БД.
• Не является потокобезопасной.
• Является легковесным объектом, создается и удаляется по необходимости.
• Жизненный цикл по умолчанию привязан к транзакции.
9. Работа с Session
1. Session предоставляет API для работы с сущностями:void persist(Object var1);
void delete(Object var1);
<T> T find(Class<T> entityClass, Object primaryKey);
2. JPQL/HQL - ООП’ный аналог sql. Сессия позволяет создавать Query и выполнять их.
3. Criteria API - это механизм, позволяющий динамически создавать запросы к бд, при помощи java кода.
Удобен в случае, если у нас есть большая вариативность потенциальных запросов, на пример если мы
можем отсортировать пользователей по n полям(имя/возраст итд) и в любой комбинации этих полей.
10. Entity
11. Persistence Context
Один или несколько EntityManager образуют или могут образовать persistence context. Наличиеpersistence context означает, что для каждой существующей на данный момент сущности есть
EntityManager, который следит за её состоянием.
PC также называется кэш первого уровня.
PC отслеживает все изменения над управляемой сущностью.
Каждый раз когда мы взаимодействуем с Session (EM) мы на самом деле взаимодействуем с PC.
По умолчанию живет столько же, сколько и транзакция. Создается лениво, т.е. при вызове метода.
12.
С точки зрения JPAкаждая
управляемая EntityMana
ger’ом сущность имеет
строго определённое
состояние и строго
определённые правила
перехода из состояния в
состояние.
13. Entity
Entity - это объект, который представляет собой отображение таблицы в Java.Может в себе содержать:
Value types: Существуют только в рамках Entity
○ базовые типы (строки, числа …)
○ Embeddable types (встроенные ссылочные типы)
○ Коллекции
Entity types (другие Entity)
14. Требования к Entity
должен быть аннотирован @Entity
наличие идентификатора @Id
public/protected конструктор без аргументов
top-level class (не вложенный)
не может быть Enum или Interface
не финальный класс
абстрактные классы могут быть
не может иметь final поля, если они участвуют в маппинге
геттеры и сеттеры, не могут быть final
Если сущность будет использоваться удаленно, в качестве
открепленной, должен implement Serializable
15.
Вопрос на 1 баллПочему мы не должны использовать final классы в качестве Entity?
16.
Превращение Entity в final ограничивает способностьHibernate использовать прокси, что, в свою очередь, не
позволяет Hibernate применять некоторые оптимизации
производительности. Без прокси ваше приложение
теряет ленивую загрузку, что снижает
производительность.
17. ID
ID могут быть:● генерируемые
● составные
Стратегии генерации ID
● Auto – стратегия по умолчанию. Берется одна из следующих 3 стратегий основываясь на
возможностях СУБД.
Identity – мапит id к авто инкрементируемой колонке. На пример к AUTO_INCREMENT in
MySQL.
Sequence – Мы определяем последовательность для генерации. При этом мы сначала
запрашиваем у СУБД следующий id и потом вставляем сущность.
● Table – id в таблице инкрементируется, самый медленный вариант, почему – читайте тут:
https://vladmihalcea.com/why-you-should-never-use-the-table-identifier-generator-with-jpa-andhibernate/
18. Embeddable
- Встраиваемый тип.- В мире java это отдельный объект
- В мире БД находится в той же таблицы, что и
сама сущность
- У такого типа нет id.
- Существует только в контексте сущности, т.е.
не может быть удален, запрошен и тд
19. Наследование
Реляционные БД не имеют прямого способа сохранения иерархии наследования классов.Для решения этой проблемы спецификация JPA выделяет 4 стратегии:
1.
MappedSuperclass – the parent classes, can't be entities
2.
Single Table – The entities from different classes with a common ancestor are placed in a single table.
3.
Joined Table – Each class has its table, and querying a subclass entity requires joining the tables.
4.
Table per Class – All the properties of a class are in its table, so no join is required.
Каждая стратегия влечет за собой разную структуру хранения данных.
20. MappedSuperclass
Самое простое, что можно придумать, этоописать в базовом классе некоторые общие
свойства и их отображение в базу данных и
потом наследоваться от базового класса,
включая это определение.
Аннотация @MappedSuperclass позволяет
включать класс и его jpa аннотации в
производный класс, не делая базовый класс
сущностью (БД не знает о его сущеcтвовании).
Типичное использование в примере выше — абстрактный базовый класс, несущий в себе
суррогатный первичный ключ.
В базе данных всё будет выглядеть, как если бы поля базового класса были определены
непосредственно в производном классе.
21. Single Table
• Стратегия по умолчанию.• Хранит все данные базового класса и всех его производных классов в одной таблице. В этой таблице будут созданные
столбцы для всех возможных полей всех производных классов и отдельный столбец, в котором будет хранится признак
класса, то есть метка, указывающая к какому конкретному классу относится эта строка.
• Базовый класс аннотируется аннотацией @Inheritance и, по желанию, @DiscriminatorColumn, в параметрах которой можно
задать наименование и тип столбца, в котором будут храниться признаки класса. К производным классам добавляется
аннотация @DiscriminatorValue, задающее значение признака класса.
22.
Single Table+ Этот подход хорош тем, что позволяет сравнительно быстро загружать объекты (не нужен Join с другими таблицами) и, при
этом, обрабатывать общие поля внешними средствами, без знания о структуре классов.
- С другой стороны, теряется возможность указывать not null ограничения для столбцов (страдает консистентность).
23.
Single TableВ качестве альтернативы сурогатной дескриминатор колонки, можно использовать
@DiscriminatorFormula - Об этом читайте сами!
24.
Joined TableДругая стратегия — создавать для каждого производного класса свою собственную таблицу, в
которой будут храниться его собственные поля. А поля базового класса — в собственной таблице
базового класса.
+ Этот подход решает проблемы предыдущего, с not null ограничениями
- Но за счёт выполнения сравнительно медленной операции join при чтении данных
производного класса из базы.
Чтобы использовать эту стратегию, необходимо аннотировать родителя:
Детей аннотировать не нужно.
25.
Joined Table-> Доменная модель
Когда селектим
дочернюю сущность
происходит left join с
родительской по
общему id.
26.
TABLE_PER_CLASSКаждый класс, и базовый и производные, получают по собственной таблице в которой есть все их
поля, а таблицы не связаны между собой.
Данная стратегия похожа на MappedSuperclass, только родитель так же является сущностью.
Чтобы использовать эту стратегию, необходимо аннотировать родителя:
Детей аннотировать не нужно.
С точки зрения бд никакого наследования нет, мы просто мапим сущность к таблице, при этом
остается возможность использовать полиморфные запросы.
Полиморфные запросы будут использовать UNION.
27.
АссоциацииАссоциации описывают, как сущности формируют отношения, основываясь на join семантике БД.
Ассоциации могут быть только между сущностями.
Ассоциации основываются на первичном и внешнем ключах. При этом ассоциация может строиться
либо на ссылке ВК-ПК у таргет объекта, либо на основе промежуточной таблицы.
28. Типы Ассоциаций
@OneToOne@OneToMany
@ManyToOne
@ManyToMany
Однонаправленные
Двунаправленные
MappedBy | JoinColumn
CascadeType.ALL
CascadeType.PERSIST
CascadeType.MERGE
CascadeType.REMOVE
CascadeType.DETACH
CascadeType.REPLICATE
CascadeType.SAVE_UPDATE
CascadeType.LOCK
29. Полезные ссылки
Общее описание:https://thorben-janssen.com/ultimate-guide-association-mappings-jpa-hibernate/
Серия статей the best way to map…:
https://vladmihalcea.com/the-best-way-to-map-a-onetoone-relationship-with-jpa-and-hibernate/
https://vladmihalcea.com/the-best-way-to-map-a-onetomany-association-with-jpa-and-hibernate/
https://vladmihalcea.com/the-best-way-to-use-the-manytomany-annotation-with-jpa-and-hibernate/
30. Проблема equals/hashCode
При написании сущностей, самый простой вариант определения equals/hashCode – на основе id.31. Варианты решения
1.Прежде чем класть сущность в коллекцию, переводить в состояние persist.
2.
Использовать @NaturalId при переопределении equals/hashCode.
3.
Генерировать идентификатор в java коде, при этом использовать его при реализации
equals()/hashCode(), а так же в качестве первичного ключа.
32. Проблема LazyInitializationException
Если мы обратимся к полям, которые подгружаются лениво при закрытом PersistenceContext, у насвозникнет LIE.
Для понимания сути этой проблемы, вы должны четко представлять, что такое:
1.
PersistenceContext
2.
Проксирование в Hibernate
3.
Ленивая загрузка
33.
Вопрос на 0.5 баллаКогда закрывается PersistenceContext?
34.
Варианты решенияПлохие:
1. Открывать транзакцию уровнем выше.
2. Выставить свойство enable_lazy_load_no_trans в true. При активации этой проперти любой
доступ к не загруженным ленивым полям будет обернут в новую Session.
3. Использовать FetchType.EAGER.
Адекватные:
1. Использовать JOIN FETCH.
2. Использовать EntityGraph.
https://thorben-janssen.com/hibernate-tips-difference-join-left-join-fetch-join/
https://www.baeldung.com/jpa-entity-graph
35. Проблема N + 1
Возникает в случаях, когда ORM выполняет 1 запрос для извлечения родительской сущности и Nзапросов для извлечения дочерних сущностей.
Если не указать стратегию явно, для
поля topic подразумевается стратегия fetch =
FetchType.EAGER. (Эта стратегия по умолчанию).
Это означает, что при выборе комментариев (select c from
Comment c) Hibernate будет заполнять значением
поле topic. Для этого он выполнит
дополнительный select для каждого комментария.
А значит, возникнет n+1 проблема.
36. Варианты решения
1.Для решения проблемы из примера, можно использовать FetchType.LAZY, но на самом деле
это не решение проблемы, а ее избегание. Т.к. когда-нибудь нам может понадобиться топик в
комментарии
2.
Join Fetch
3.
Entity graph
37.
Темы для самоизучения1.
@DynamicInsert(true)
2.
@DynamicUpdate(true)
38. Кэши
Кеш первого уровня (First-level cache);
Кеш второго уровня (Second-level cache);
Кеш запросов (Query cache);
39. Кэши
Стратегии кэширования:READ_ONLY
NONSTRICT_READ_WRITE
READ_WRITE
TRANSACTIONAL
programming