@PersistenceContext
EntityManager em;
Java Platform, Enterprise Edition (Java EE) 8 Учебник по Java EE |
Назад | Вперёд | Содержание |
Сущности управляются entity manager-ом, который представлен объектами javax.persistence.EntityManager
. Каждый объект EntityManager
связан с контекстом персистентности: набором объектов сущностей, которые существуют в хранилище данных. Контекст персистентности определяет область, в которой создаются, сохраняются и удаляются объекты сущностей. Интерфейс EntityManager
определяет методы, которые используются для взаимодействия с контекстом персистентности.
Здесь рассматриваются следующие темы:
API EntityManager
создаёт и удаляет объекты сущностей, осуществляет выборку объектов сущности по первичному ключу сущности и позволяет выполнять запросы к сущностям.
Здесь рассматриваются следующие темы:
С помощью Entity Manager-а, управляемого контейнером, контекст персистентности объекта EntityManager
автоматически распространяется контейнером на все компоненты приложения, которые используют объект EntityManager
в рамках единого API транзакций Java (JTA).
Транзакции JTA обычно включают вызовы между компонентами приложения. Для завершения транзакции JTA этим компонентам обычно требуется доступ к одному контексту персистентности. Это происходит, когда EntityManager
инъецируется в компоненты приложения посредством аннотации javax.persistence.PersistenceContext
. Контекст персистентности автоматически распространяется с текущей транзакцией JTA, а ссылки EntityManager
, которые сопоставлены с одним и тем же юнитом персистентности, обеспечивают доступ к контексту персистентности в этой транзакции. Благодаря автоматическому распространению (propagating) контекста персистентности компонентам приложения не нужно передавать ссылки на объекты EntityManager
друг другу, чтобы вносить изменения в одной транзакции. Контейнер Java EE управляет жизненным циклом entity manager-ов, управляемых контейнером.
Чтобы получить объект EntityManager
, инъецируйте EntityManager в компонент приложения:
@PersistenceContext
EntityManager em;
С другой стороны, с помощью entity manager-а, управляемого приложением, контекст персистентности не распространяется на компоненты приложения, а жизненный цикл объектов EntityManager
управляется приложением.
Управляемые приложением entity manager-ы используются, когда приложению необходим доступ к контексту персистентности, который не распространяется с транзакцией JTA через объекты EntityManager
в конкретном юните персистентности. В этом случае каждый EntityManager
создаёт новый изолированный контекст персистентности. EntityManager
и связанный с ним контекст персистентности создаются и уничтожаются приложением явным образом. Они также используются, когда прямое инъецирование объектов EntityManager
невозможно, поскольку объекты EntityManager
не являются потокобезопасными. Объекты EntityManagerFactory
являются потокобезопасными.
В этом случае приложения создают объекты EntityManager
, используя метод createEntityManager
из javax.persistence.EntityManagerFactory
.
Чтобы получить объект EntityManager
, сначала необходимо получить объект EntityManagerFactory
, инъецировав его в компонент приложения аннотацией javax.persistence.PersistenceUnit
:
@PersistenceUnit
EntityManagerFactory emf;
Затем получите EntityManager
из объекта EntityManagerFactory
:
EntityManager em = emf.createEntityManager();
Entity manager-ы, управляемые приложением, не распространяют автоматически контекст транзакции JTA. Такие приложения должны вручную получить доступ к менеджеру транзакций JTA и добавить информацию о разграничении транзакций при выполнении операций с объектами сущностей. Интерфейс javax.transaction.UserTransaction
определяет методы для запуска, фиксации и отката транзакций. Инъецируйте объект UserTransaction
, создав переменную объекта с аннотацией @Resource
:
@Resource
UserTransaction utx;
Чтобы начать транзакцию, вызовите метод UserTransaction.begin
. Когда все операции с объектами сущностей завершены, вызовите метод UserTransaction.commit
для фиксации транзакции. Метод UserTransaction.rollback
используется для отката текущей транзакции.
В следующем примере показано, как управлять транзакциями в приложении, в котором используется EntityManager, управляемый приложением:
@PersistenceUnit
EntityManagerFactory emf;
EntityManager em;
@Resource
UserTransaction utx;
...
em = emf.createEntityManager();
try {
utx.begin();
em.persist(SomeEntity);
em.merge(AnotherEntity);
em.remove(ThirdEntity);
utx.commit();
} catch (Exception e) {
utx.rollback();
}
Метод EntityManager.find
используется для выборки объектов из хранилища данных по их первичному ключу:
@PersistenceContext
EntityManager em;
public void enterOrder(int custID, CustomerOrder newOrder) {
Customer cust = em.find(Customer.class, custID);
cust.getOrders().add(newOrder);
newOrder.setCustomer(cust);
}
Объекты сущности управляются с помощью операций объекта EntityManager
. Объекты сущностей могут находиться в одном из четырёх состояний: новое, управляемое (managed), отсоединённое (detached) или удалённое (removed).
Новые объекты сущностей ещё не сохранены в хранилище и не связаны с контекстом персистентности.
Управляемые объекта уже сохранены в хранилище и связаны с контекстом персистентности.
Отсоединённые объекты сущности сохранены в хранилище, но в настоящее время не связаны с контекстом персистентности.
Удалённые объекты сохранены в хранилище, связаны с контекстом персистентности и отмечены для удаления из хранилища.
Новые объекты сущностей становятся управляемыми и сохраняются в хранилище либо путём вызова метода persist
, либо с помощью каскадной операции persist
, вызываемой из связанных сущностей, которые имеют элементы cascade=PERSIST
или cascade=ALL
, установленные в аннотациях отношений. Это означает, что данные объекта сохраняются в базе данных, когда транзакция, связанная с операцией persist
, завершена. Если объект уже управляется, операция persist
игнорируется, хотя операция persist
будет каскадно связана со связанными объектами, у которых элемент cascade
установлен в PERSIST
или ALL
в аннотации отношений. Если persist
вызывается для удалённого объекта, объект становится управляемым. Если объект отсоединён, тогда либо выполнение persist
выбросит исключение IllegalArgumentException
, либо фиксация транзакции завершится неудачно. Следующий метод выполняет операцию persist
:
@PersistenceContext
EntityManager em;
...
public LineItem createLineItem(CustomerOrder order, Product product,
int quantity) {
LineItem li = new LineItem(order, product, quantity);
order.getLineItems().add(li);
em.persist(li);
return li;
}
Операция persist
распространяется на все объекты, связанные с вызывающим объектом, у которых для элемента cascade
установлено значение ALL
или PERSIST
в аннотации отношений:
@OneToMany(cascade=ALL, mappedBy="order")
public Collection<LineItem> getLineItems() {
return lineItems;
}
Управляемые объекты сущностей удаляются путём вызова метода remove
или каскадной операции remove
, вызываемой из связанных сущностей, которые имеют cascade=REMOVE
или cascade=ALL
в аннотации отношений. Если метод remove
вызывается для нового объекта, операция remove
игнорируется, хотя remove
будет каскадно переходить к связанным объектам, которые имеют элемент cascade
, установленный в значение REMOVE
или ALL
в аннотации отношения. Если remove
вызывается для отсоединённого объекта, то либо remove
сгенерирует IllegalArgumentException
, либо фиксация транзакции завершится неудачно. Если вызывается для уже удалённого объекта, remove
будет игнорироваться. Данные сущности будут удалены из хранилища после завершения транзакции или в результате операции flush
.
В следующем примере все объекты LineItem
, связанные с заказом, также удаляются, так как CustomerOrder.getLineItems
имеет cascade=ALL
, установленный в аннотации отношения:
public void removeOrder(Integer orderId) {
try {
CustomerOrder order = em.find(CustomerOrder.class, orderId);
em.remove(order);
}...
Состояние сохранённых объектов синхронизируется с базой данных, когда транзакция, с которой связан этот объект, фиксируется. Если управляемый объект находится в двунаправленном отношении с другим управляемым объектом, данные будут сохранены в зависимости от стороны-владельца отношения.
Чтобы принудительно синхронизировать управляемый объект с хранилищем данных, вызовите метод flush
объекта EntityManager
. Если объект связан с другим объектом, а аннотация отношения имеет элемент cascade
, установленный в PERSIST
или ALL
, данные связанного объекта будут синхронизированы с хранилищем данных при вызове flush
.
Если объект удаляется, вызов flush
удалит данные объекта из хранилища данных.
Юнит персистентности определяет набор всех классов сущностей, которые управляются объектами EntityManager
в приложении. Этот набор классов сущностей представляет данные, содержащиеся в одном хранилище данных.
Юниты персистентности определяются в файле конфигурации persistence.xml
. Ниже приведён пример файла persistence.xml
:
<persistence>
<persistence-unit name="OrderManagement">
<description>This unit manages orders and customers.
It does not rely on any vendor-specific features and can
therefore be deployed to any persistence provider.
</description>
<jta-data-source>jdbc/MyOrderDB</jta-data-source>
<jar-file>MyOrderApp.jar</jar-file>
<class>com.widgets.CustomerOrder</class>
<class>com.widgets.Customer</class>
</persistence-unit>
</persistence>
Этот файл определяет персистентный модуль с именем OrderManagement
, который использует источник данных jdbc/MyOrderDB
с поддержкой JTA. Элементы jar-file
и class
определяют управляемые классы: классы сущностей, встраиваемые классы и сопоставленные родительские классы. Элемент jar-file
определяет JAR-файлы, которые видны упакованному юниту персистентности, которые содержат управляемые классы сущностей, тогда как элементы class
перечисляют управляемые классы сущностей явным образом.
Элементы jta-data-source
(для источников данных, поддерживающих JTA) и non-jta-data-source
(для источников данных, не поддерживающих JTA) задают глобальные имя JNDI источника данных, который будет использоваться контейнером.
JAR-файл или каталог, в каталоге META-INF
которого содержится persistence.xml
, называется корнем юнита персистентности. Область видимости юнита персистентности определяется корнем юнита персистентности. Каждый юнит персистентности идентифицируется по имени, уникальному для области видимости юнита персистентности.
Юниты персистентности могут быть упакованы как часть файла WAR или EJB JAR или как файл JAR, который затем может быть включён в WAR-файл или EAR.
Если вы упакуете юнит персистентности как набор классов в файле EJB JAR, persistence.xml
должен быть помещён в каталог META-INF
EJB JAR.
Если вы упакуете юнит персистентности как набор классов в файле WAR, файл persistence.xml
должен находиться в каталоге WEB-INF/classes/META-INF
файла WAR.
Если вы упакуете юнит персистентности в файл JAR, который будет включён в WAR-файл или EAR, файл JAR должен находиться в одном из следующих каталогов
Каталог WEB-INF/lib
WAR
Каталог одной из библиотек EAR-файла
Замечание: В Java Persistence API 1.0 файлы JAR могут находиться в корне файла EAR в качестве корня юнита персистентности. Это больше не поддерживается. Переносимые приложения должны использовать каталог библиотеки EAR-файла в качестве корня юнита персистентности. |
Назад | Вперёд | Содержание |