540 likes | 909 Views
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 Управление транзакциÑми
E N D
Обзор • Архитектура 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 сущности • Стратегии слияния
Entity manager и Persistence Context • Entity Manager – API для создания, чтения, записи и удаления сущностей из БД • API инкапсулирован в интерфейсе EntityManager • Managed сущность – это сущность, которую создал или получил Entity Manager • Набор сущностей, managed данным Entity Manager’ом в данное время называется persistence context этого Entity Manager • Только одна сущность данного типа с одинаковым идентификатором может содержаться в persistence context 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, жизненным циклом которого управляет контейнер, называется Container-Managed Entity Manager (CMEM) • В зависимости от способа работы 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 для данного блока: <persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0"> <persistence-unit name="EmployeeService" transaction-type="RESOURCE_LOCAL"> 15
Управление JPA транзакциями. Определения • Синхронизациятранзакции(transaction synchronization) – принцип, согласно которому PC связывается с транзакцией • Ассоциациятранзакции(transaction association) – акт (процесс) связывания PC с транзакцией • Продление транзакции(transaction propagation) – процесс начала совместного использования (sharing) PC несколькими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 • Даже если с T1уже был ассоциирован контекст PC0 • Весь последующий код, работающий в этой же транзакцииT1 будет использовать PC1 • ВесьPC1будет доступен в транзакции T1, которая может его произвольно модифицировать • Пример. Extended PC (example_05-04) 18
Коллизия контекстов • Предположим, что SFUL1 был вызван из stateless бина SLESS1, который работал в транзакции T1и имел контекст PC0 • В момент вызова SFUL1произойдет ассоциация(eager)PC1с T1 • Но 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 транзакция получается из application-managed EM вызовом em.getTransaction() • 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
Detachment и merging • Никакие программные изменения над detachedсущностью не будут commit в БД, т.к. EM не отслеживает эту сущность • Слияние (merge)это процесс обратной интеграции detached сущности в EM • Возможно offline изменение сущности (возможно в другой JVM) с последующим слиянием этой сущности в EM и commit в БД 45
Merge detached сущностей • Метод E1=em.merge(E)делает merge detached сущности Eобратно в PC • Сущность 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