Главная страница

ОглавлениеCore


Скачать 1.53 Mb.
НазваниеОглавлениеCore
Дата17.05.2023
Размер1.53 Mb.
Формат файлаpdf
Имя файлаpolnaya_metodichka (1).pdf
ТипДокументы
#1138113
страница20 из 25
1   ...   17   18   19   20   21   22   23   24   25
optional – boolean (по умолчанию true) – определяет, может ли значение поля или свойства быть null. Игнорируется для примитивных типов. Но если тип поля не примитивного типа, то при попытке сохранения сущности будет выброшено исключение.
2. fetch – FetchType (по умолчанию EAGER) – определяет, должен ли этот атрибут извлекаться незамедлительно (EAGER) или лениво (LAZY). Это необязательное требование
JPA, и провайдерам разрешено незамедлительно загружать данные, даже для которых установлена ленивая загрузка.
Без аннотации @Basic при получении сущности из БД по умолчанию ее поля базового типа загружаются принудительно (EAGER) и значения этих полей могут быть null.

Для чего нужна аннотация Column?
@Column сопоставляет поле класса столбцу таблицы, а ее атрибуты определяют поведение в этом столбце, используется для генерации схемы базы данных.
@Basic vs @Column:
1. Атрибуты @Basic применяются к сущностям JPA, тогда как атрибуты @Column применяются к столбцам базы данных.
2. @Basic имеет атрибут optional, который говорит о том, может ли поле объекта быть null
или нет; с другой стороны атрибут nullable аннотации @Column указывает, может ли соответствующий столбец в таблице быть null.
3. Можно использовать @Basic, чтобы указать, что поле должно быть загружено лениво.
4. Аннотация @Column позволяет указать имя столбца в таблице и ряд других свойств:

insertable/updatable – можно ли добавлять/изменять данные в колонке, по умолчанию true;

length – длина, для строковых типов данных, по умолчанию 255.
Коротко, в @Column задаем constraints, а в @Basic – FetchTypes.
Для чего нужна аннотация Access?
Определяет тип доступа к полям сущности. Для чтения и записи этих полей есть два подхода:
1. Field access (доступ по полям). При таком способе аннотации маппинга (Id, Column,...)
размещаются над полями, и Hibernate напрямую работает с полями сущности, читая и записывая их.
2. Property access (доступ по свойствам). При таком способе аннотации размещаются над методами-геттерами, но не над сеттерами.
По умолчанию тип доступа определяется местом, в котором находится аннотация @Id. Если она будет над полем – это будет AccessType.FIELD, если над геттером – это
AccessType.PROPERTY.
Чтобы явно определить тип доступа у сущности, нужно использовать аннотацию @Access,
которая может быть указана у сущности, Mapped Superclass и Embeddable class, а также над полями или методами.
Поля, унаследованные от суперкласса, имеют тип доступа этого суперкласса.
Если у одной сущности определены разные типы доступа, то нужно использовать аннотацию
@Transient для избежания дублирования маппинга.
Для чего нужна аннотация @Cacheable?
@Cacheable – необязательная аннотация JPA, используется для указания того, должна ли сущность храниться в кеше второго уровня.
В JPA говорится о пяти значениях shared-cache-mode из persistence.xml, который определяет как будет использоваться second-level cache:


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), поэтому кеш второго уровня доступен одновременно в нескольких сессиях или контекстах персистентности. Кеш второго уровня требует некоторой настройки и поэтому не включен по умолчанию. Настройка кеша заключается в конфигурировании реализации кеша и разрешения сущностям быть закешированными.

Hibernate не реализует сам никакого in-memory сache, а использует существующие реализации кешей.
Как работать с кешем 2 уровня?
Чтение из кеша второго уровня происходит только в том случае, если нужный объект не был найден в кеше первого уровня.
Hibernate поставляется со встроенной поддержкой стандарта кеширования Java JCache, а также двух популярных библиотек кеширования: Ehcache и Infinispan.
В Hibernate кеширование второго уровня реализовано в виде абстракции, то есть необходимо предоставить любую ее реализацию. Например, можно использовать следующих провайдеров: Ehcache, OSCache, SwarmCache, JBoss TreeCache. Для Hibernate требуется только реализация интерфейса org.hibernate.cache.spi.RegionFactory, который инкапсулирует все детали, относящиеся к конкретным провайдерам. По сути RegionFactory действует как мост между Hibernate и поставщиками кеша. В качестве примера воспользуемся Ehcache. Для этого:

добавим мавен-зависимость кеш-провайдера нужной версии;

включим кеш второго уровня и определить конкретного провайдера;
hibernate.cache.use_second_level_cache=true
hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory

установим у нужных сущностей JPA-аннотацию @Cacheable, обозначающую, что сущность нужно кешировать, и Hibernate-аннотацию @Cache, настраивающую детали кеширования, у которой в качестве параметра указать стратегию параллельного доступа.
Стратегии параллельного доступа к объектам:
Проблема заключается в том, что кеш второго уровня доступен из нескольких сессий сразу и несколько потоков программы могут одновременно в разных транзакциях работать с одним и тем же объектом. Следовательно надо как-то обеспечивать их одинаковым представлением этого объекта.

1   ...   17   18   19   20   21   22   23   24   25


написать администратору сайта