ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 01.12.2023

Просмотров: 420

Скачиваний: 2

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.


ENABLE_SELECTIVE: только сущности с аннотацией @Cacheable (равносильно значению по умолчанию @Cacheable(value = true)) будут сохраняться в кеше второго уровня;

DISABLE_SELECTIVE: все сущности будут сохраняться в кеше второго уровня, за исключением сущностей, помеченных @Cacheable(value = false) как некешируемые;

ALL: сущности всегда кешируются, даже если они помечены как некешируемые;

NONE: ни одна сущность не кешируется, даже если помечена как кешируемая. При данной опции имеет смысл вообще отключить кеш второго уровня;

UNSPECIFIED: применяются значения по умолчанию для кеша второго уровня,
определенные Hibernate. Это эквивалентно тому, что вообще не используется shared- cache-mode, так как Hibernate не включает кеш второго уровня, если используется режим UNSPECIFIED.
Аннотация @Cacheable размещается над классом сущности. Ее действие распространяется на эту сущность и ее наследников, если они не определили другое поведение.
Для чего нужны аннотации @Embedded и @Embeddable?
@Embeddable – аннотация JPA, размещается над классом для указания того, что класс является встраиваемым в другие классы.
@Embedded – аннотация JPA, используется для размещения над полем в классе-сущности для указания того, что внедряется встраиваемый класс.
Как смапить составной ключ?
Составной первичный ключ, также называемый составным ключом, представляет собой комбинацию из двух или более столбцов для формирования первичного ключа таблицы.
@IdClass
Допустим, есть таблица с именем Account, и она имеет два столбца – accountNumber и accountType, которые формируют составной ключ. Чтобы обозначить оба этих поля как части составного ключа, необходимо создать класс, например, ComplexKey с этими полями.
Затем нужно аннотировать сущность Account аннотацией @IdClass(ComplexKey.class) и объявить поля из класса ComplexKey в сущности Account с такими же именами и аннотировать их с помощью @Id.
@EmbeddedId
Допустим, что необходимо сохранить некоторую информацию о книге с заголовком и языком в качестве полей первичного ключа. В этом случае класс первичного ключа, BookId, должен быть аннотирован @Embeddable.
Затем нужно встроить этот класс в сущность Book, используя @EmbeddedId.
Для чего нужна аннотация ID? Какие @GeneratedValue вы знаете?
Аннотация @Id определяет простой (не составной) первичный ключ, состоящий из одного поля. В соответствии с JPA, допустимые типы атрибутов для первичного ключа:

примитивные типы и их обертки;

строки;



BigDecimal и BigInteger;

java.util.Date и java.sql.Date.
Если хотим, чтобы значение первичного ключа генерировалось автоматически, необходимо добавить первичному ключу, отмеченному аннотацией @Id, аннотацию @GeneratedValue.
Возможны 4 варианта:
1. AUTO (default). Указывает, что Hibernate должен выбрать подходящую стратегию для конкретной базы данных, учитывая ее диалект, так как у разных БД разные способы по умолчанию. Поведение по умолчанию – исходить из типа поля идентификатора.
2. IDENTITY. Для генерации значения первичного ключа будет использоваться столбец
IDENTITY, имеющийся в базе данных. Значения в столбце автоматически увеличиваются вне текущей выполняемой транзакции(на стороне базы, так что этого столбца не увидим, что позволяет базе данных генерировать новое значение при каждой операции вставки. В
промежутках транзакций сущность будет сохранена.
3. SEQUENCE. Тип генерации, рекомендуемый документацией Hibernate. Для получения значений первичного ключа Hibernate должен использовать имеющиеся в базе данных механизмы генерации последовательных значений (Sequence). В БД можно будет увидеть дополнительную таблицу. Но если БД не поддерживает тип SEQUENCE, то Hibernate автоматически переключится на тип TABLE. В промежутках транзакций сущность не будет сохранена, так как Hibernate возьмет из таблицы id hibernate-sequence и вернется обратно в приложение. SEQUENCE – это объект базы данных, который генерирует инкрементные целые числа при каждом последующем запросе.
4. TABLE. Hibernate должен получать первичные ключи для сущностей из создаваемой для этих целей таблицы, способной содержать именованные сегменты значений для любого количества сущностей. Требует использования пессимистических блокировок, которые помещают все транзакции в последовательный порядок и замедляет работу приложения.
Расскажите про аннотации @JoinColumn и @JoinTable? Где и для чего они
используются?
@JoinColumn используется для указания столбца FOREIGN KEY, используемого при установлении связей между сущностями или коллекциями. Только сущность-владелец связи может иметь внешние ключи от другой сущности (владеемой). Но можно указать
@JoinColumn как во владеющей таблице, так и во владеемой, но столбец с внешними ключами все равно появится во владеющей таблице.
Особенности использования:

@OneToOne: означает, что появится столбец в таблице сущности-владельца связи,
который будет содержать внешний ключ, ссылающийся на первичный ключ владеемой сущности;

@OneToMany/@ManyToOne: если не указать на владеемой стороне связи
@mappedBy, создается joinTable с ключами обеих таблиц. Но при этом же у владельца создается столбец с внешними ключами.
@JoinColumns используется для группировки нескольких аннотаций @JoinColumn, которые используются при установлении связей между сущностями или коллекциями, у которых составной первичный ключ и требуется несколько колонок для указания внешнего ключа.


В каждой аннотации @JoinColumn должны быть указаны элементы name и referencedColumnName.
@JoinTable используется для указания связывающей (сводной, третьей) таблицы между двумя другими таблицами.
Для чего нужны аннотации @OrderBy и @OrderColumn, чем они отличаются?
@OrderBy указывает порядок, в соответствии с которым должны располагаться элементы коллекций сущностей, базовых или встраиваемых типов при их извлечении из БД. Если в кеше есть нужные данные, то сортировки не будет, так как @OrderBy просто добавляет к sql- запросу Order By, а при получении данных из кеша, обращения к БД нет. Эта аннотация может использоваться с аннотациями @ElementCollection, @OneToMany, @ManyToMany.
При использовании с коллекциями базовых типов, которые имеют аннотацию
@ElementCollection, элементы этой коллекции будут отсортированы в натуральном порядке,
по значению базовых типов.
Если это коллекция встраиваемых типов (@Embeddable), то, используя точку ("."), можно сослаться на атрибут внутри встроенного атрибута.
Если это коллекция сущностей, то у аннотации @OrderBy можно указать имя поля сущности,
по которому сортировать эти сущности:
Если не указывать у @OrderBy параметр, то сущности будут упорядочены по первичному ключу.
В случае с сущностями доступ к полю по точке (".") не работает. Попытка использовать вложенное свойство, например, @OrderBy ("supervisor.name") повлечет Runtime Exceprtion.
@OrderColumn создает в таблице столбец с индексами порядка элементов, который используется для поддержания постоянного порядка в списке, но этот столбец не считается частью состояния сущности или встраиваемого класса.
Hibernate отвечает за поддержание порядка как в базе данных при помощи столбца, так и при получении сущностей и элементов из БД. Hibernate отвечает за обновление порядка при записи в базу данных, чтобы отразить любое добавление, удаление или иное изменение порядка, влияющее на список в таблице.
@OrderBy vs @OrderColumn
Порядок, указанный в @OrderBy, применяется только в рантайме при выполнении запроса к
БД, То есть в контексте персистентности, в то время как при использовании @OrderColumn,
порядок сохраняется в отдельном столбце таблицы и поддерживается при каждой вставке/обновлении/удалении элементов.
Для чего нужна аннотация Transient?
@Transient используется для объявления того, какие поля у сущности, встраиваемого класса или Mapped SuperClass не будут сохранены в базе данных.
Persistent fields (постоянные поля) – это поля, значения которых будут по умолчанию сохранены в БД. Ими являются любые не static и не final поля.
Transient fields (временные поля):

static и final поля сущностей;



иные поля, объявленные явно с использованием Java-модификатора transient либо
JPA-аннотации @Transient.
Какие шесть видов блокировок (lock) описаны в спецификации JPA (или какие
есть значения у enum LockModeType в JPA)?
В порядке от самого ненадежного и быстрого, до самого надежного и медленного:
1. NONE – без блокировки.
2. OPTIMISTIC (синоним READ в JPA 1) – оптимистическая блокировка: если при завершении транзакции кто-то извне изменит поле @Version, то будет сделан
RollBack транзакции и будет выброшено OptimisticLockException.
3. OPTIMISTIC_FORCE_INCREMENT (синоним WRITE в JPA 1) – работает по тому же алгоритму, что и LockModeType.OPTIMISTIC за тем исключением, что после commit значение поля Version принудительно увеличивается на 1. В итоге после каждого коммита поле увеличится на 2 (увеличение, которое можно увидеть в Post-Update +
принудительное увеличение).
4. PESSIMISTIC_READ – данные блокируются в момент чтения, и это гарантирует, что никто в ходе выполнения транзакции не сможет их изменить. Остальные транзакции смогут параллельно читать эти данные. Использование этой блокировки может вызывать долгое ожидание блокировки или даже выкидывание
PessimisticLockException.
5. PESSIMISTIC_WRITE – данные блокируются в момент записи, и никто с момента захвата блокировки не может в них писать и не может их читать до окончания транзакции, владеющей блокировкой. Использование этой блокировки может вызывать долгое ожидание блокировки.
6. PESSIMISTIC_FORCE_INCREMENT – ведет себя как PESSIMISTIC_WRITE, но в конце транзакции увеличивает значение поля @Version, даже если фактически сущность не изменилась.
Оптимистичное блокирование – подход предполагает, что параллельно выполняющиеся транзакции редко обращаются к одним и тем же данным, позволяет им свободно выполнять любые чтения и обновления данных. Но при окончании транзакции производится проверка,
изменились ли данные в ходе выполнения данной транзакции и, если да, транзакция обрывается и выбрасывается OptimisticLockException. Оптимистичное блокирование в JPA
реализовано с помощью внедрения в сущность специального поля версии:
@Version
private long version;
Поле, аннотирование @Version, может быть целочисленным или временнЫм. При завершении транзакции, если сущность была заблокирована оптимистично, будет проверено, не изменилось ли значение @Version кем-либо еще после того, как данные были прочитаны, и, если изменилось, будет выкинуто OptimisticLockException. Использование этого поля позволяет отказаться от блокировок на уровне базы данных и сделать все на уровне JPA, улучшая уровень конкурентности.
Позволяет отказаться от блокировок на уровне БД и делать все с JPA.
Пессимистичное блокирование – подход ориентирован на транзакции, которые часто конкурируют за одни и те же данные, поэтому блокируется доступ к данным в тот момент,

когда происходит чтение. Другие транзакции останавливаются, когда пытаются обратиться к заблокированным данным, и ждут снятия блокировки (или кидают исключение).
Пессимистичное блокирование выполняется на уровне базы и поэтому не требует вмешательств в код сущности.
Блокировки ставятся с помощью вызова метода lock() у EntityManager, в который передается сущность, требующая блокировки и уровень блокировки:
EntityManager em = entityManagerFactory.createEntityManager();
em.lock(company1, LockModeType.OPTIMISTIC);
Какие два вида кэшей (cache) вы знаете в JPA и для чего они нужны?

first-level cache (кеш первого уровня) кеширует данные одной транзакции;

second-level cache (кеш второго уровня) кэширует данные транзакций от одной фабрики сессий. Провайдер JPA может, но не обязан реализовывать работу с кешем второго уровня.
Кеш первого уровня – это кеш сессии (Session), который является обязательным, это и есть
PersistenceContext. Через него проходят все запросы.
Если выполняем несколько обновлений объекта, Hibernate старается отсрочить (насколько это возможно) обновление этого объекта для того, чтобы сократить количество выполненных запросов в БД. Например, при пяти обращении к одному и тому же объекту из БД в рамках одного persistence context, запрос в БД будет выполнен один раз, а остальные четыре загрузки будут выполнены из кеша. Если закроем сессию, то все объекты, находящиеся в кеше, теряются, а далее – либо сохраняются в БД, либо обновляются.
Особенности кеша первого уровня:

включен по умолчанию, его нельзя отключить;

связан с сессией (контекстом персистентности), то есть разные сессии видят только объекты из своего кеша и не видят объекты, находящиеся в кешах других сессий;

при закрытии сессии PersistenceContext очищается – кешированные объекты,
находившиеся в нем, удаляются;

при первом запросе сущности из БД она загружается в кеш, связанный с этой сессией;

если в рамках этой же сессии снова запросим эту же сущность из БД, то она будет загружена из кеша и повторного SQL-запроса в БД сделано не будет;

сущность можно удалить из кеша сессии методом evict(), после чего следующая попытка получить эту же сущность повлечет обращение к базе данных;

метод clear() очищает весь кеш сессии.
Если кеш первого уровня привязан к объекту сессии, то кеш второго уровня привязан к объекту-фабрике сессий (Session Factory object), поэтому кеш второго уровня доступен одновременно в нескольких сессиях или контекстах персистентности. Кеш второго уровня требует некоторой настройки и поэтому не включен по умолчанию. Настройка кеша заключается в конфигурировании реализации кеша и разрешения сущностям быть закешированными.