Transcript Типы Entity Manager
Entity Manager
1
Обзор
Архитектура Java Persistence API Entity manager и Persistence Context Persistence Provider и Entity Manager Factory Типы Entity Manager Transaction-Scoped Entity Manager Extended Entity Manager Application-Managed Entity Manager Управление транзакциями Resource-Local транзакции Выбор Entity manager
Обзор
Операции Entity Manager Сохранение сущности Поиск сущности Удаление сущности Каскадные операции Синхронизация с БД Detached сущности Merging Работа с detached сущностями Решение проблемы доступа к lazy атрибутам detached сущности Стратегии слияния
Архитектура Java Persistence API
4
Entity manager и Persistence Context
Entity Manager
– API для создания, чтения, записи и удаления сущностей из БД API инкапсулирован в интерфейсе EntityManager
Managed
сущность – это сущность, которую создал или получил Entity Manager Набор сущностей, managed данным Entity Manager’ом в данное время называется Entity Manager
persistence context
этого Только context одна сущность данного типа с одинаковым идентификатором может содержаться в persistence 5
Persistence Provider и Entity Manager Factory
Persistence Provider
определяет конкретную имплементацию интерфейса Entity Manager Отвечает за все обязанности Entity Manager: генерацию SQL, обработку JPQL и т.д.
Entity Manager’ы создаются и конфигурируются фабрикой
EntityManagerFactory
XML конфигурация данной EntityManagerFactory называется
persistence unit
6
Persistence Provider и Entity Manager Factory
Persistence unit определяет такие параметры как: Persistence Provider Тип Entity Manager Сущности, с которыми может работать Entity Manager данного persistence unit Базу данных, с которой работает данный EM Прочие настройки Persistence unit именован, чтобы различать Entity Manager’ов, созданных разными фабриками Одна фабрика может создавать несколько Entity Manager’ов Набор persistence unit’ов данного приложения образует файл META-INF/persistence.xml
7
Persistence Provider и Entity Manager Factory
Persistence unit определяет такие параметры как: Persistence Provider Тип Entity Manager Сущности, с которыми может работать Entity Manager данного persistence unit Базу данных, с которой работает данный EM Прочие настройки Persistence unit именован , чтобы различать Entity Manager’ов, созданных разными фабриками Одна фабрика может создавать несколько Entity Manager’ов Набор persistence unit’ов данного приложения образует файл META-INF/persistence.xml
8
Типы Entity Manager
Entity Manager и Persistence Context тесно связаны, хотя PC не является частью API. Приложение никогда не работает с PC Существует
3 типа
Entity Manager. Каждый взаимодействует с PC по-разному : Container-Managed (Transaction Scoped) EM Container-Managed (Extended) EM Application-Managed EM Понимание совместной работы EM данного типа с PC критично в изучении JPA 9
Container-Managed Entity Manager
EM, жизненным циклом которого управляет называется
(CMEM)
контейнер ,
Container-Managed Entity Manager
В зависимости от способа работы EM с PC выделяют два подтипа: Transaction-Scoped Entity Manager (TSEM) Extended Entity Manager (EEM) Для получения ссылки на любой CMEM служит аннотация
@PersistenceContext
Схема работы CMEM зависит от JPA транзакции 10
Transaction-Scoped Entity Manager
Когда над EM совершается некоторая операция (find, add, etc), EM проверяет, ассоциирован ли PC с данной JPA транзакцией Если PC ассоциирован с JTA, EM использует этот PC Если нет – EM создает пустой PC, ассоциирует его с текущей JPA транзакцией и использует Когда транзакция завершается (commit), в БД изменяются все сущности, отслеженные EM в данном PC После завершения транзакции (commit) PC разрушается 11
Extended Entity Manager
Может использоваться только для stateful beans Detached сущность – это сущность, которая была managed некоторым EM, но была удалена из PC после его закрытия Определяется с помощью:
@PersistenceContext(unitName="EmployeeService", type=
PersistenceContextType.EXTENDED
)
PC создается в момент создания stateful бина, удаляется в момент его удаления 12
Extended Entity Manager
В каждый момент завершения транзакции, все изменения с предыдущей транзакции, проведенными над сущностями PC, отслеженные EM уходят в базу.
Разница с TSEM в том, что после завершения транзакции PC не разрушается Extended EM экономит roundtrip в БД, хорош для сервисов, которым необходима поддержка состояния Минус в том, что stateful бины не сильно распространены 13
Application-Managed Entity Manager
Приложение управляет созданием EM из фабрики управлением транзакциями закрытием EM PC создается немедленно после создания EM фабрикой и длится до явного закрытия EM Пример. Application Managed EM в среде Java SE (example_05-01) Пример. Application Managed EM в среде Java EE (example_05-02) 14
Управление транзакциями
Транзакция
определяет когда новая, измененная или удаленная сущность будет синхронизирована с БД JPA поддерживает 2 вида транзакций:
Resource Local
JTA
Container-Manager EM могут работать только с JPA Application Managed EM могут работать транзакции с любым типом Тип транзакции для данного persistence unit определяется в persistence.xml для данного блока:
Управление JPA транзакциями. Определения
Синхронизация транзакции
synchronization) –
принцип
связывается с транзакцией (transaction , согласно которому PC
Ассоциация транзакции
акт ( (transaction association) –
процесс
) связывания PC с транзакцией
Продление транзакции
PC
несколькими
(transaction propagation) – процесс начала совместного использования (sharing) EM в пределах
одной
транзакции 16
Transaction-Scoped Persistence Context
PC продляется так же, как продляется JPA транзакция После вызова метода, TSEM проверяет, есть ли продленный PC Если нет, то создает его EM создает PC lazily, только если вызвана операция на EM Таким образом, различные части приложения ( разные бины ) могут использовать один и тот же PC , если они работают в используют одной транзакции , несмотря на то, что разные экземпляры EM Пример. PC Propagation (example_05-03) 17
Extended Persistence Context
Extended PC ( PC1 ) создается в момент создания stateful бина SFUL1 Непосредственно (eager) в момент вызова stateful бина (или части метода бина), работающего в транзакции T1 , PC1 ассоциируется с T1 Даже если с PC0 T1 уже был ассоциирован контекст Весь последующий код, работающий в этой же транзакции T1 будет использовать PC1
Весь
PC1 может его будет доступен в транзакции T1 , которая
произвольно
модифицировать Пример. Extended PC (example_05-04) 18
Коллизия контекстов
Предположим, что SFUL1 был вызван из stateless бина SLESS1 , который работал в транзакции T1 и имел контекст PC0 В момент вызова SFUL1 PC1 с T1 произойдет ассоциация (eager) Но PC0 уже продлен (propagated) с транзакцией T1 Произойдет
коллизия контекстов
Может существовать только один активный PC в данной транзакции Провайдер выбросит исключение Хорошо, когда stateful бин – первый в цепочке вызовов, все последующие вызовы используют transaction scoped PC 19
Как бороться с коллизией контекстов
На stateful бине, определяющем extended PC: Использовать транзакционный атрибут REQUIRES_NEW Постоянное создание новых транзакций может отрицательно сказаться на производительности системы Использование разных транзакций может оказаться логически неверным Использовать транзакционный атрибут NOT_SUPPORTED Может использоваться только если логика метода не пересекается с вызывающей логикой и не требует транзакции Пример. Избегание коллизий (example_05-05) 20
Наследование persistence context’ов
Если stateful бин (SB1) с extended PC (PC1) создает другой stateful бин (SB2) с extended PC, то коллизии не произойдет Вместо этого дочерний бин SB2 будет создан с контекстом PC1 Контекст унаследуется Пример. Наследование контекстов (example_05-06) 21
Application-Managed Persistence Contexts
Жизненный цикл application managed PC совпадает с жизненным циклом application managed EM AM EM создается запросом фабрики и получением ссылки на EM из фабрики Приложение ассоциирует AM PC с JTA транзакцией одним из двух способов: EM создается в транзакции Вызовом em.joinTransaction() 22
Application-Managed Persistence Contexts
AM EM не продляют (propagate) свой PC. Следствия: Поэтому не может быть коллизий контекстов Для того, чтобы share контекст с другими компонентами, необходимо передавать EM С данной транзакцией можно ассоциировать произвольное количество application managed PC Если PC синхронизирован с транзакцией, то изменения будут записаны в БД, даже если соответствующий EM будет закрыт Пример. Наследование контекстов (example_05-07) 23
Resource-Local транзакции
Resource-Local транзакции полностью управляются приложением. Нет вмешательства Java EE сервера RL транзакция получается из вызовом em.getTransaction() application-managed EM EntityTransaction имитирует JTA UserTransaction 24
Resource-Local транзакции
Операции EntityTransaction определены через транзакционные механизмы JDBC. Нет глобального (XA) транзакционного поведения RL транзакция не зависит от JTA транзакции и может commit или rollback без какого-либо влияния на JTA
RL транзакция может использоваться для логирования
Пример. Наследование контекстов (example_05-08) 25
Rollback транзакции и состояние сущности
Модель памяти Java не транзакционна Когда транзакция завершается (commit), PC смотрит на все свои объекты, которые удалены, изменены или созданы и генерирует SQL для обновления БД Выполнение этого SQL может прерваться (rollback). Произойдет 2 вещи: Изменения в БД откатятся PC очистится, все managed сущности станут detached Произойдет рассинхранизация БД и detached объектов в памяти Рассмотреть возможность сделать попытку второго commit и выполнить слияние (merge) сущностей 26
Какой Entity manager использовать
Для большинства Java EE приложений подойдет Container-Managed Transaction-Scoped EM Таковой была имплементация многих коммерческих ORM фреймворков (TopLink) Наиболее понятна семантика работы Идея Extended PC была введена впервые в JPA Есть performance плюсы Есть ограничения (коллизии) 27
Какой Entity manager использовать
Использование Application-Managed PC в средах не очень хорошая идея
Java EE
Нет context propagation Application-Managed PC Может отлично использоваться в фреймворках
Java SE
средах, а так же в custom
Смешивать
разные типы EM в архитектуре одного приложения определенно
плохая
идея 28
Операции Entity Manager. Сохранение сущности
Метод em.persist( e ) принимает новую сущность и делает ее managed Если е уже managed, ничего не происходит При вызове persist() данные
не
сохраняются в БД. Будут сохранены при синхронизации PC с БД (commit, flush) При вызове persist() вне транзакции в transaction scoped EM, будет возбужден TransactionRequiredException Однако, EM может теперь над Java экземпляром e
отслеживать
все изменения 29
Операции Entity Manager. Сохранение сущности
EntityExistException будет возбужден: При вызове persist(), если EM обнаружит, что сущность с тем же идентификатором уже managed При commit в БД, если на уровне SQL обнаружится, что сущность с тем же идентификатором уже существует в БД Пример: 30
Операции Entity Manager. Поиск сущности
em.find(key) выбирает сущность из БД или из PC Возвращенная сущность будет managed За исключением вызова find() вне транзакции в transaction-scoped EM. В этом случае она будет detached 31
Операции Entity Manager. Поиск сущности
Когда target сущность в отношении one-to-one или many-to-
one
существует в БД и ее ключ SQL для выборки этой сущности известен , нет нужды делать getReference(key) возвращает прокси объект, в котором определен только идентификатор сущности EntityNotFoundException будет возбужден при выхове любого метода, кроме getID() Проксируемая сущность должна существовать в таблице 32
Операции Entity Manager. Удаление сущности
em.remove(e) используется для удаления сущности e Данные реально удалятся из БД, при commit транзакции Обслуживание отношений выполняет приложение, не JPA!
33
Операции Entity Manager. Удаление сущности
Только для managed сущности может быть вызван em.remove() Вызов em.remove() вне транзакции в transaction-scoped EM приведет к TransactionRequiredException В остальных типах EM ничего не произойдет: Никакой exception не возбудится Сущность не удалится из БД 34
Каскадные операции
По умолчанию операция EM применяется только к сущности, передаваемой в качестве аргумента. Не
(cascade) продолжается
на другие сущности в отношении Это
не
ограничение спецификации. Приложение должно иметь контроль над тем, что удаляется, что создается и т.д.
В примере ниже разумно продолжать (cascade) операцию persist автоматически при сохранении адреса 35
Cascade Persist
Все каскадные установки однонаправленные Операция persist для managed сущности не имеет никакого эффекта для атрибутов этой сущности, но для ее выполнятся cascade persist операции 36
Cascade Remove
Упоминалось о том, что это обязанность приложения занулять ссылки. Ставить везде CascadeType.REMOVE не разумно Только в случае one-to-one и one-to-many можно относительно безопасно использовать каскадное удаление
При условии, что target сущности можно безопасно удалить 37
Синхронизация с БД
PC
сбрасывается (flush)
каждый раз, когда генерируется и исполняется SQL Flush происходит в двух случаях: Транзакция завершается (commit) Делается вызов em.flush() Провайдер может сделать flush в любой момент, например: JPQL зависит от данных PC Flush происходит для сущностей: Новых Измененных Удаленных 38
Синхронизация с БД. Persist
Flush новой сущности логически эквивалентен вызову persist второй раз на этой сущности 39
Синхронизация с БД. Persist
В общем виде, исключение будет возбуждено, если managed сущность имеет ссылки на сущности:
не
-managed Detached сущность Новая сущность Исключение из этого правила: Detached сущность является target сущностью one-to one или many-to-one отношения Новая сущность имеет каскадный атрибут CascadeType.PERSIST В идеале, при persist весь граф объектов должен быть managed 40
Синхронизация с БД. Remove
Удаляется сущность: Так как flush в БД может произойти в любое время, мы должны сущностей
как можно раньше
обеспечить необходимые зануления foreign ключей source Другими словами, занулить все отношения, которые ссылаются на удаляемую сущность Непонимание этого факта может приводить к мистически, плавающим ошибкам 41
Detached сущности
Существует несколько причин, по которым сущность может стать detached: транзакция в transaction-scoped EM commit, PC разрушается application-managed PC закрывается stateful бин с extended PC удаляется (метод @Remove) вызван clear() метод у EM когда происходит rollback, все сущности в PC становятся detached когда сущность сериализуется, она отсоединяется от PC 42
Detached и Managed сущности
У managed сущности мы можем вызвать любой информацию из БД lazy атрибут. JPA сделает SQL вызов и выберет нужную Lazy-loaded было Варианты: атрибуты detached сущности, к которым вызова в момент, когда сущность еще была определяет поведение провайдера в этом случае. не managed представляют проблему. Спецификация JPA не Провайдер все же постарается подгрузить сущность Сущность останется не проинициализированной Выкинет исключение 43
Пример. Lazy fetch Detached сущности
44
Detachment и merging
Никакие программные изменения над
не
сущность detached сущностью будут commit в БД, т.к. EM не отслеживает эту
Слияние (merge)
это процесс обратной интеграции detached сущности в EM Возможно offline изменение сущности (возможно в другой JVM) с последующим commit в БД слиянием этой сущности в EM и 45
Merge detached сущностей
Метод E E1 =em.merge( обратно в PC E ) делает merge detached сущности Сущность E не станет managed, ею будет
E1
!!!
46
Merge detached сущностей
Если X является detached сущностью, состояние X скопируется в уже существующую managed сущность X' с тем же идентификатором, либо создается новая managed сущность X' Если X это новая сущность, то создается новая managed сущность X' и состояние X копируется в X' Если X это удаленная сущность, исключение IllegalArgumentException будет возбуждено (либо транзакция откатиться) 47
Merge detached сущностей
Если X это managed сущность, она игнорируется, однако, операция merge будет cascade на другие отношения из X, если эти отношения аннотированы cascade атрибутами cascade=MERGE or cascade=ALL Для всех сущностей Y на которые ссылается X и имеющих cascade атрибут cascade=MERGE или cascade=ALL, Y merge рекурсивно как Y'. Для каждой такой Y на которую ссылается X, X' будет ссылаться на Y' EM не будет merge атрибуты, помеченные как lazy, если к ним не было доступа, когда X была managed Если к lazy атрибуту A был доступ, когда X была managed (атрибут был подгружен), после чего A был занулен, атрибут А будет занулен у merged сущности 48
Пример. Merge detached сущностей
49
Пример. Merge detached сущностей
50
Работа с detached сущностями
Пример. Проблема доступа к lazy данным detached сущности (example_05-09) 51
Решение проблемы доступа к lazy атрибутам detached сущности
Планирование detachment Инициирование lazy загрузки (example_05-10) Использование eager загрузки Использование load tuners Избегание detachment Либо не работаем с detached сущностями из клиента (jsp). Пока сущность managed, копируем все необходимые данные в DTO объекты Либо сохраняем PC открытым все время, пока нужен доступ к сущности (example_05-11), (example_05-12) 52
Стратегии слияния
Использование статического сервиса.
(example_05-13)
Service
Использование сервиса, накапливающего данные.
Edit Session
(example_05-14)
53