Вы находитесь на странице: 1из 10

1. ORM (англ. Object-relational mapping, рус.

Объектно-реляционное отображение) - технология программирования,


которая связывает базы данных с концепциями объектно-ориентированных языков программирования, создавая
"виртуальную объектную базу данных"

JPA (Java Persistence API) это спецификация Java EE и Java SE, описывающая систему управления
сохранением java объектов в таблицы реляционных баз данных в удобном виде.

Hibernate? — одна из наиболее популярных реализаций ORM-модели. Объектно-реляционная модель описывает


отношения между программными объектами и записями в БД.

2. EntityManager это интерфейс, который описывает API для всех основных операций над Entity, получение данных и
других сущностей JPA. По сути главный API для работы с JPA. Основные операции:
1) Для операций над Entity: persist (добавление Entity под управление JPA), 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
4) Общие операции над EntityManager или всеми Entities: close, isOpen, getProperties, setProperty, clear.

3.
1) Entity класс должен быть отмечен аннотацией Entity или описан в XML файле конфигурации JPA,
2) Entity класс должен содержать public или protected конструктор без аргументов (он также может иметь
конструкторы с аргументами),
3) Entity класс должен быть классом верхнего уровня (top-level class),
4) Entity класс не может быть enum или интерфейсом,
5) Entity класс не может быть финальным классом (final class),
6) Entity класс не может содержать финальные поля или методы, если они участвуют в маппинге (persistent final
methods or persistent final instance variables),
7) Если объект Entity класса будет передаваться по значению как отдельный объект (detached object), например через
удаленный интерфейс (through a remote interface), он так же должен реализовывать Serializable интерфейс,
8) Поля Entity класс должны быть напрямую доступны только методам самого Entity класса и не должны быть
напрямую доступны другим классам, использующим этот Entity. Такие классы должны обращаться только к методам
(getter/setter методам или другим методам бизнес-логики в Entity классе),
9) Entity класс должен содержать первичный ключ, то есть атрибут или группу атрибутов которые уникально
определяют запись этого Entity класса в базе данных.

4. Может ли абстрактный класс быть Entity? - может, но не может быть инициализирован

5. может наследоваться от не Entity

6. Может ли Entity класс наследоваться от других Entity классов? - Да

7. Может ли не Entity класс наследоваться от Entity класса? - Да

8. Встраиваемый (Embeddable) класс это класс который не используется сам по себе, только как часть одного или
нескольких Entity классов. Entity класс могут содержать как одиночные встраиваемые классы, так и коллекции таких
классов. Также такие классы могут быть использованы как ключи или значения map. Во время выполнения каждый
встраиваемый класс принадлежит только одному объекту Entity класса и не может быть использован для передачи
данных между объектами Entity классов (то есть такой класс не является общей структурой данных для разных
объектов). В целом, такой класс служит для того чтобы выносить определение общих атрибутов для нескольких Entity,
можно считать что JPA просто встраивает в Entity вместо объекта такого класса те атрибуты, которые он содержит.
Такие классы должны удовлетворять тем же правилам что Entity классы, за исключением того что они не обязаны
содержать первичный ключ и быть отмечены аннотацией Entity,
Embeddable класс должен быть отмечен аннотацией Embeddable или описан в XML файле конфигурации JPA.
9. Mapped Superclass это класс от которого наследуются Entity, он может содержать аннотации JPA, однако сам такой
класс не является Entity, ему не обязательно выполнять все требования установленные для Entity (например, он может
не содержать первичного ключа). Такой класс не может использоваться в операциях EntityManager или Query. Такой
класс должен быть отмечен аннотацией MappedSuperclass или соответственно описан в xml файле.

10. Какие три типа стратегии наследования мапинга (Inheritance Mapping Strategies) описаны в JPA?

В JPA описаны три стратегии наследования мапинга (Inheritance Mapping Strategies), то есть как JPA будет работать с
классами-наследниками Entity:
1) одна таблица на всю иерархию наследования (a single table per class hierarchy) — все entity, со всеми наследниками
записываются в одну таблицу, для идентификации типа entity определяется специальная колонка “discriminator
column”. Например, если есть entity Animals c классами-потомками Cats и Dogs, при такой стратегии все entity
записываются в таблицу Animals, но при это имеют дополнительную колонку animalType в которую соответственно
пишется значение «cat» или «dog».Минусом является то что в общей таблице, будут созданы все поля уникальные для
каждого из классов-потомков, которые будет пусты для всех других классов-потомков. Например, в таблице animals
окажется и скорость лазанья по дереву от cats и может ли пес приносить тапки от dogs, которые будут всегда иметь
null для dog и cat соответственно.

2) объединяющая стратегия (joined subclass strategy) — в этой стратегии каждый класс entity сохраняет данные в свою
таблицу, но только уникальные колонки (не унаследованные от классов-предков) и первичный ключ, а все
унаследованные колонки записываются в таблицы класса-предка, дополнительно устанавливается связь (relationships)
между этими таблицами, например в случае классов Animals (см.выше), будут три таблицы animals, cats, dogs, причем
в cats будет записана только ключ и скорость лазанья, в dogs — ключ и умеет ли пес приносить палку, а в animals все
остальные данные cats и dogs c ссылкой на соответствующие таблицы. Минусом тут являются потери
производительности от объединения таблиц (join) для любых операций.

3) одна таблица для каждого класса (table per concrete class strategy) — тут все просто каждый отдельный класс-
наследник имеет свою таблицу, т.е. для cats и dogs (см.выше) все данные будут записываться просто в таблицы cats и
dogs как если бы они вообще не имели общего суперкласса. Минусом является плохая поддержка полиморфизма
(polymorphic relationships) и то что для выборки всех классов иерархии потребуются большое количество отдельных
sql запросов или использование UNION запроса.

11. Как мапятся Enum – аннотация @Enumerated (EnumType.x)


enumType.ORDINAL == в базу пишется порядковый номер enum
enumType.STRING == пишется имя.

12. @Temporal. Deprecated since java8

13. Для коллекций создаются отдельные таблицы, в некоторых случаях с добавлением столбца со значением ключа. С
сущностями объекты сохраняемой коллекции взаимодействуют с помощью связей (OneToMany, ManyToOne,
ManyToMany)
@ElementCollection
@OrderBy
Если у нашей сущности есть поле с коллекцией, то мы привыкли ставить над ним аннотации @OneToMany либо
@ManyToMany. Но данные аннотации применяются в случае, когда это коллекция других сущностей (entities). Если у
нашей сущности коллекция не других сущностей, а базовых или встраиваемых (embeddable) типов для этих случаев в
JPA имеется специальная аннотация @ElementCollection, которая указывается в классе сущности над полем коллекции.
Все записи коллекции хранятся в отдельной таблице, то есть в итоге получаем две таблицы: одну для сущности,
вторую для коллекции элементов.
@CollectionTable - позволяет редактировать таблицу с коллекцией, прочитать

14. Существуют следующие четыре типа связей


1. OneToOne (связь один к одному, то есть один объект Entity может связан не больше чем с один объектом другого
Entity ),
2. OneToMany (связь один ко многим, один объект Entity может быть связан с целой коллекцией других Entity),
3. ManyToOne (связь многие к одному, обратная связь для OneToMany),
4. ManyToMany (связь многие ко многим)
Каждую из которых можно разделить еще на два вида:
1. Bidirectional
2. Unidirectional — ссылка на связь устанавливается у всех Entity, то есть в случае OneToOne A-B в Entity A есть ссылка
на Entity B, в Entity B есть ссылка на Entity A, Entity A считается владельцем этой связи (это важно для случаев
каскадного удаления данных, тогда при удалении A также будет удалено B, но не наоборот).Unidirectional - ссылка на
связь устанавливается только с одной стороны, то есть в случае OneToOne A-B только у Entity A будет ссылка на Entity
B, у Entity B ссылки на A не будет.

15. Владелец связи — сущность, содержащая атрибут-объект владеемого класса. Поля владеемого класса отмечается
аннтоцией @JoinColumn(имя столбца) имя столбца в котором хранится ссылка на владеемую сущность
Во владеемом классе поле, содержащее объект класса-владельца помечается @One/ManyToOne/Many...
(имя_поля_класса-владельца). На объекты владеемого класса распространяются действия, совершаемые с объектом
класса-владельца, это называется каскадированием и настраивается параметром CascadeType

16. Каскадирование - это когда мы выполняем какое-то действие с целевой сущностью, то же самое действие будет
применено к связанной сущности.

JPA CascadeType:
ALL - распространяет все операции, включая специфичные для Hibernate, от родительского объекта к дочернему
объекту.
PERSIST - делает временный экземпляр постоянным. CascadeType.PERSIST передает операцию persist от
родительского объекта к дочернему объекту . Когда мы сохраняем личность лица, адрес также будет сохранена.
MERGE - операция слияния копирует состояние данного объекта в постоянный объект с тем же идентификатором.
CascadeType.MERGE передает операцию слияния от родителя к дочерней сущности.
REMOVE - удаляет строку, соответствующую объекту, из базы данных, а также из постоянного контекста.
DETACH - удаляет объект из постоянного контекста. Когда мы используем CascadeType.DETACH, дочерняя сущность
также будет удалена из постоянного контекста.
Hibernate CascadeType:
LOCK - повторно присоединяет сущность и связанную дочернюю сущность с постоянным контекстом снова.
REFRESH - повторно считывают значение данного экземпляра из базы данных. В некоторых случаях мы можем
изменить экземпляр после сохранения в базе данных, но позже нам нужно отменить эти изменения.
REPLICATE - используется, когда у нас более одного источника данных, и мы хотим, чтобы данные были
синхронизированы. С CascadeType.REPLICATE операция синхронизации также распространяется на дочерние объекты
всякий раз, когда выполняется над родительским объектом.
SAVE_UPDATE - распространяет ту же операцию на связанный дочерний объект. Это полезно, когда мы используем
специфичные для Hibernate операции, такие как save, update и saveOrUpdate.

17. В JPA описаны два типа fetch стратегии:


1) LAZY — данные поля будут загружены только во время первого доступа к этому полю,
2) EAGER — данные поля будут загружены немедленно.
Используются по умолчанию:
one(many)to many — lazy

18.

1. new - объект создан, не имеет primary key


2. managed - объект создан, имеет primary key, управляется JPA
3. detached - объект создан, не управляется JPA
4. removed - объект создан, управляется JPA, будет удален при commit-e

19.-23. persist()
• new → managed, и объект будет сохранен в базу при commit-е транзакции или в результате flush операций
• managed → операция игнорируется, однако зависимые Entity могут поменять статус на managed, если у них
есть аннотации каскадных изменений
• removed → managed
• detached → exception сразу или на этапе commit-а транзакции

remove()
• new → операция игнорируется, однако зависимые Entity могут поменять статус на removed, если у них есть
аннотации каскадных изменений и они имели статус managed
• managed → removed и запись объект в базе данных будет удалена при commit-е транзакции (также
произойдут операции remove для всех каскадно зависимых объектов)
• removed → операция игнорируется
• detached → exception сразу или на этапе commit-а транзакции,

merge()
• detached → либо данные будут скопированы в существующий managed entity с тем же первичным ключом,
либо создан новый managed в который скопируются данные
• new → будет создана новый managed entity, в который будут скопированы данные прошлого объекта
• managed → операция игнорируется, однако операция merge сработает на каскадно зависимые Entity, если их
статус не managed
• removed → exception сразу или на этапе commit-а транзакции,

refresh()
• managed → будут восстановлены все изменения из базы данных данного Entity, также произойдет refresh
всех каскадно зависимых объектов
• new, removed, detached → exception

detach()
• managed, removed → detached.
• new, detached → операция игнорируется

24. @Basic
@Basic — указывает на простейший тип маппинга данных на колонку таблицы базы данных. Также в параметрах
аннотации можно указать fetch стратегию доступа к полю и является ли это поле null или нет.
Самый простой тип сопоставления со столбцом базы данных. Базовая аннотация может быть применена к
постоянному свойству или переменной экземпляра любого из следующих типов: примитивные типы Java, оболочки
примитивных типов, String, BigInteger, BigDecimal, Date, Calendar, Time, Timestamp, byte[], Byte[], char[], Character[],
enums, и любой другой тип, который реализует java.io.Serializable.
Использование базовой аннотации является необязательным для постоянных полей и свойств этих типов. Если базовая
аннотация не указана для такого поля или свойства, то будут применяться значения по умолчанию базовой
аннотации.

@Basic vs @Column:
1. Атрибуты @Basic применяются к сущностям JPA, тогда как атрибуты @Column применяются к столбцам базы
данных.
2. @Basic имеет атрибут optional, который говорит о том, может ли поле объекта быть null или нет; с другой стороны
атрибут nullable аннотации @Column указывает, может ли соответствующий столбец в таблице быть null.
3. Мы можем использовать @Basic, чтобы указать, что поле должно быть загружено лениво.
4. Аннотация @Column позволяет нам указать имя столбца в таблице и ряд других свойств:
a. insertable/updatable - можно ли добавлять/изменять данные в колонке, по умолчанию true;
b. length - длина, для строковых типов данных, по умолчанию 255.
Коротко, в коламн мы заем констраинтс, а в басик ФЕТЧ ТАЙП"
25. @Column нужна чтобы указать детали столбца в таблице.

@Column аннотации имеет много атрибутов, такие как name, length, nullable и unique.
Элемент name указывает имя столбца в таблице. Элемент length указывает его длину. атрибут nullable определяет,
является ли элемент обнуляемым, и unique атрибут определяет, является ли уникальным столбец.
Если мы не укажем эту аннотацию, имя поля будет считаться именем столбца в таблице.

26. @Access: определяет тип доступа, поле или свойство. Поле — является значением по умолчанию и если нужно,
чтобы hibernate использовал методы getter/setter, то их необходимо задать для нужного свойства.

27. @Cacheable это аннотация JPA и позволяет объекту быть закэшированным. Hibernate поддерживает эту аннотацию
в том же ключе.

28. Аннотация @Embeddable позволяет указать класс, экземпляры которого хранятся как внутренняя часть сущности-
владельца. Эта аннотация не имеет атрибутов .

Аннотация @Embedded используется для указания постоянного поля или свойства сущности, значение которой
является экземпляром встраиваемого класса. По умолчанию определения столбцов, указанные в классе @Embeddable ,
применяются к таблице объекта-владельца, но их можно переопределить с помощью @AttributeOverride

29. Маппинг составного ключа. Помечается как Embeddable. idCLASS

30. С помощью @Id мы указываем первичный ключ (Primary Key) данного класса.

Типы переменных для @Id: примитивные и примитивные типы-оболочки, String, Date, BigDecimal, BigInteger.

Стратегии генерации @Id - знать все!!!!


GenerationType.AUTO является типом генерации по умолчанию. Выбирает стратегию генерации на основе
конкретного диалекта базы данных. Для большинства популярных баз данных он выбирает GenerationType.SEQUENCE.
GenerationType.IDENTITY является самым простым в использовании, но не самый лучший с точки зрения
производительности. Он опирается на автоматически увеличивающийся столбец базы данных и позволяет базе
данных генерировать новое значение при каждой операции вставки. Hibernate требует значения первичного ключа
для каждого управляемого объекта и поэтому должен немедленно выполнить оператор вставки. Это предотвращает
использование различных методов оптимизации, таких как пакетная обработка JDBC. (Идентити делает инсерт до
персиста).
GenerationType.SEQUENCE использует последовательность базы данных для генерации уникальных значений.
Для получения следующего значения из последовательности базы данных требуются дополнительные операторы
select. Но это не влияет на производительность для большинства приложений. (Секвенс делает селект, чтобы
сгенерить id).
GenerationType.TABLE используется редко. Он моделирует последовательность, сохраняя и обновляя ее
текущее значение в таблице базы данных, что требует использования пессимистических блокировок, которые
помещают все транзакции в последовательный порядок. Это замедляет работу вашего приложения

31. @JoinColumn

Указывает столбец для присоединения к связной сущности или коллекции элементов. Если сама аннотация
@JoinColumn имеет значение по умолчанию, то предполагается наличие одного столбца соединения и применяются
значения по умолчанию.
https://docs.oracle.com/javaee/7/api/javax/persistence/JoinColumn.html

@JoinColumn - в связях вида One2Many/Many2One сторона, находящаяся в собственности обычно называется


стороной “многих”. Обычно, это сторона, которая держит внешний ключ. Эта аннотация, фактически, описывает
физический (как в бд) маппинг на стороне “многих”. В атрибут name этой аннотации дается название колонки,
которая будет присоединена к таблице “многих” и которая будет заполняться значениями первичных ключей из
таблицы-собственника. Таким образом - мы даём название для внешнего ключа. По факту - использование этой
аннотации опционально, т.к. хибернейт, проанализировав сущность - поймет сам, что в таблице для этого класса
нужно создать колонку, обозначающую внешний ключ, и даст ей соответствующее название “{name}_id”.
@JoinTable
Определяет сопоставление ассоциации. Он применяется к владельцу ассоциации.
@JoinTable обычно используется при отображении связей «многие ко многим» и однонаправленных связей «один ко
многим». Он также может использоваться для сопоставления двунаправленных ассоциаций «многие к одному» или
«один ко многим», однонаправленных связей «многие к одному» и связей «один к одному» (как двунаправленных, так
и однонаправленных).
Когда @JoinTable используется при отображении отношения с встраиваемым классом на стороне-владельце
отношения, содержащая сущность, а не встраиваемый класс считается владельцем отношения.
Если @JoinTable аннотация отсутствует, применяются значения по умолчанию для элементов аннотации.

32. @OrderBy
Определяет порядок элементов коллекции, оцениваемой ассоциацией или коллекцией элементов, в тот момент,
когда ассоциация или коллекция извлекаются.
https://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/OrderBy.html

@OrderBy могут быть применены к элементу коллекции. Когда OrderBy применяется к коллекции элементов базового
типа, порядок будет по значению базовых объектов, а имя свойства или поля не используется. При указании порядка
для коллекции элементов встраиваемого типа необходимо использовать точечную нотацию для указания атрибута
или атрибутов, которые определяют порядок.

@OrderColumn - как работает, где ставится


Указывает столбец, который используется для поддержания постоянного порядка списка. @OrderColumn указывается
в отношении OneToMany или ManyToMany или в коллекции элементов. @OrderColumn указывается на стороне
отношения, ссылающейся на коллекцию, которая должна быть упорядочена.

Различия между @OrderBy и @OrderColumn

@OrderBy в запросе отсортирует, а в кэше вернет неотсортированный порядок.

@OrderColumn сортирует данные с учетом данных в колонке, и в кеше и в запросе.

Указанный порядок @OrderBy применяется только во время выполнения при получении результата запроса.

@OrderColumn приводит к постоянному упорядочению соответствующих данных.

33. Transient – означает, что поле не пишется в базу, не сериализуется

34. Блокировки — механизм, регулирующий работу с данными в БД, когда к ним обращаются две и более транзакции
одновременно. Есть два подхода к организации работы блокировок — оптимистический и пессимистический:

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

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

Разница в том, что в первом случае обеспечивается более высокий уровень конкурентности при доступе к базе,
который оплачивается необходимостью переповтора транзакций, в случае коллизии. Во втором случае транзакции
гарантируется, что только она будет иметь полный доступ к данным, но за счёт понижения уровня конкурентности и
затрат времени на ожидание блокировки.
Блокировок же есть 6 видов:

- NONE — без блокировки;

- OPTIMISTIC

- OPTIMISTIC_FORCE_INCREMENT — с принудительным увеличением поля версионности

- PESSIMISTIC_READ

- PESSIMISTIC_WRITE

- PESSIMISTIC_FORCE_INCREMENT

35. Кэш в Хибернейте есть двух уровней: L1 и L2

L1 – кэширует данные только одной транзакции, всегда включен и не может быть отключен. Не потокобезопасен.
Очищается методом clear()

L2 – кеширует данные более чем одной сессии/транзакции. Кэш второго уровня создается в области фабрики
EntityManagerFactory и доступен для использования во всех EntityManager, которые создаются с использованием этой
конкретной фабрики.

36. hibernate.cache.use_second_level_cache=true

hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory

Чтобы сделать объект пригодным для кэширования второго уровня, мы помечаем его аннотацией @Cache или

@Cacheable, специфичной для Hibernate, и указываем стратегию параллельного использования кэша:


1) ALL — все Entity могут кэшироваться в кэше второго уровня
2) NONE — кеширование отключено для всех Entity
3) ENABLE_SELECTIVE — кэширование работает только для тех Entity, у которых установлена аннотация Cacheable(true),
для всех остальных кэширование отключено
4) DISABLE_SELECTIVE — кэширование работает для всех Entity, за исключением тех у которых установлена аннотация
Cacheable(false)
5) UNSPECIFIED — кеширование не определенно, каждый провайдер JPA использует свою значение по умолчанию для
кэширования

Hibernate также поддерживает QueryCache, который может хранить результаты запроса. Вам необходимо активировать его в
файле persistence.xml, установив для параметра
hibernate.cache.use_query_cache=true
и определив
hibernate.cache.region.factory_class
Кроме того, вам также необходимо активировать кэширование для конкретного запроса, для которого вы хотите кэшировать
результаты, вызывая
setCacheable(true) хранит id и по ним ищет объекты по нимв кэше объекты****

Стратегии параллельного доступа к объектам


Проблема заключается в том, что кэш второго уровня доступен из нескольких сессий сразу и несколько потоков программы
могут одновременно в разных транзакциях работать с одним и тем же объектом. Следовательно надо как-то обеспечивать их
одинаковым представлением этого объекта.
❖ READ_ONLY: Используется только для сущностей, которые никогда не изменяются (будет выброшено исключение, если
попытаться обновить такую сущность). Очень просто и производительно. Подходит для некоторых статических данных, которые
не меняются.
❖ NONSTRICT_READ_WRITE: Кэш обновляется после совершения транзакции, которая изменила данные в БД и закоммитила
их. Таким образом, строгая согласованность не гарантируется, и существует небольшое временное окно между обновлением
данных в БД и обновлением тех же данных в кэше, во время которого параллельная транзакция может получить из кэша
устаревшие данные.
❖ READ_WRITE: Эта стратегия гарантирует строгую согласованность, которую она достигает, используя «мягкие» блокировки:
когда обновляется кэшированная сущность, на нее накладывается мягкая блокировка, которая снимается после коммита
транзакции. Все параллельные транзакции, которые пытаются получить доступ к записям в кэше с наложенной мягкой
блокировкой, не смогут их прочитать или записать и отправят запрос в БД. Ehcache использует эту стратегию по умолчанию.
❖ TRANSACTIONAL: полноценное разделение транзакций. Каждая сессия и каждая транзакция видят объекты, словно они
работали с ними последовательно одна транзакция за другой. Плата за это — блокировки и потеря производительности."

37. HQL – Hibernate Query Language – язык запросов Hibernate. SQL-подобный язык, вместо имен и столбцов таблиц
баз данных использует имена Entity-классов и их атрибудты. Поддерживает плиморфизм. Нестандартизован.

JPQL – Java Persistence Query Language – стандартизованный язык запросов, подобный HQL.

38. Hibernate Criteria API является более объектно-ориентированным для запросов, которые получают результат из
базы данных (DML). Для операций update, delete или других DDL манипуляций использовать Criteria API нельзя.
Критерии используются только для выборки из базы данных в более объектно-ориентированном стиле. Используется
для динамических запросов

Вот некоторые области применения Criteria API:

Criteria API поддерживает проекцию, которую мы можем использовать для агрегатных функций вроде sum(), min(),

max() и т.д.

Criteria API может использовать ProjectionList для извлечения данных только из выбранных колонок.

Criteria API может быть использована для join запросов с помощью соединения нескольких таблиц, используя методы

createAlias(), setFetchMode() и setProjection().

Criteria API поддерживает выборку результатов согласно условиям (ограничениям). Для этого используется метод add()

с помощью которого добавляются ограничения (Restrictions).

Criteria API позволяет добавлять порядок (сортировку) к результату с помощью метода addOrder().

Criteria JPA – минус – не видно запросов, создается в некоторых случаях много объектов; низкая производительность

39. N+1 Select problem.

Допустим, у вас есть коллекция Car объектов (строк базы данных), и у каждого Car есть коллекция Wheel объектов
(также строк). Другими словами, Car→ Wheel это отношение 1-ко-многим.

Теперь предположим, что вам нужно пройтись по всем машинам, и для каждой распечатать список колес:
SELECT * FROM Cars;
И тогда для каждого Car:
SELECT * FROM Wheel WHERE CarId = ?
Другими словами, у вас есть один выбор для автомобилей, а затем N дополнительных выборов, где N - общее
количество автомобилей.
В качестве альтернативы можно получить все колеса и выполнить поиск в памяти:
SELECT * FROM Wheel
Это уменьшает количество обращений к базе данных с N+1 до 2. Большинство инструментов ORM предоставляют
несколько способов предотвратить выбор N+1.
https://stackoverflow.com/questions/97197/what-is-the-n1-selects-problem-in-orm-object-relational-mapping

Решения:
bidirectional
unidirectional OneToMany unidirectional ManyToone
solution OneToMany/ManyToOne

jpql native jpql native jpql native


join fetch + - + - + -

FetchMode.SUBSELECT + - - - +/-** -

BatchSize + + - - +/-** +/-**

EntityGraph + - + - + -

SqlResultSetMapping - - - + - -/+***

HibernateSpecificMapping - -* - + - +
* - если не используем аннотацию JoinColumn и оставляем связанную третью таблицу
** - работает только при выборке собственника с коллекцией зависимых сущностей
*** - работает только при выборке дочерней сущности с ссылкой на родительскую сущность
Выводы:
1. Лучшим вариантом решения N+1 проблемы для простых запросов (1-3 уровня вложенности связанных объектов)
будет join fetch и jpql запрос. Следует придерживаться тактики, когда мы выбираем из jpql и нативного запроса jpql
2. Если у нас имеется нативный запрос, и мы не заботимся о слабой связанности кода - то хорошим вариантом будет
использование Hibernate Specific Mapping. В противном случае стоит использовать @SqlResultSetMapping
3. В случаях, когда нам нужно получить по-настоящему много данных, и у нас jpql запрос - лучше всего использовать
EntityGraph
4. Если мы знаем примерное количество коллекций, которые будут использоваться в любом месте приложения -
можно использовать @BatchSize

40. Entity Grpah.


FetchType.LAZY используется почти во всех случаях, чтобы получить хорошо работающее и масштабируемое
приложение. Определение графа сущностей не зависит от запроса и определяет, какие атрибуты нужно извлечь из
базы данных. Граф сущностей может использоваться в качестве выборки или графика загрузки. Если используется
график выборки, только атрибуты, указанные в графе сущностей, будут обрабатываться как FetchType.EAGER. Все
остальные атрибуты будут ленивыми. Если используется график загрузки, все атрибуты, которые не указаны в графе
объектов, сохранят свой тип выборки по умолчанию.
https://www.baeldung.com/jpa-entity-graph
https://thoughts-on-java.org/jpa-21-entity-graph-part-1-named-entity/

Для этого существует EntityGraph API, используется он так: с помощью аннотации @NamedEntityGraph для Entity,
создаются именованные EntityGraph объекты, которые содержат список атрибутов у которых нужно поменять
fetchType на EAGER, а потом данное имя указывается в hits запросов или метода find. В результате fetchType атрибутов
Entity меняется, но только для этого запроса. Существует две стандартных property для указания EntityGraph в hit:
1) javax.persistence.fetchgraph — все атрибуты перечисленные в EntityGraph меняют fetchType на EAGER, все остальные
на LAZY
2) javax.persistence.loadgraph — все атрибуты перечисленные в EntityGraph меняют fetchType на EAGER, все остальные
сохраняют свой fetchType (то есть если у атрибута, не указанного в EntityGraph, fetchType был EAGER, то он и
останется EAGER)С помощью NamedSubgraph можно также изменить fetchType вложенных объектов Entity.
https://docs.google.com/document/d/1F5t0pjTb5KpCiSEwSEdbCneBmOxnd4eNInXTPsbAnck/edit?usp=sharing

Определение именованного графа сущностей выполняется аннотацией @NamedEntityGraph в сущности. Он


определяет уникальное имя и список атрибутов ( attributeNodes ), которые должны быть загружены.
https://thoughts-on-java.org/jpa-21-entity-graph-part-1-named-entity/
https://www.baeldung.com/jpa-entity-graph

Вам также может понравиться