- •Обозначения и сокращения
- •введение
- •1. Установка и настройка инструментальных средств
- •1.1. Установка и подготовка к работе операционной системы
- •1.2. Установка программного обеспечения
- •1.3. Создание таблиц в базе данных
- •2. Основы Java EE 6
- •2.1. Распределенные многоуровневые приложения
- •2.2. Контейнеры Java EE
- •2.3. Сервер GlassFish v3
- •2.4. Структура приложения
- •2.5. Конфигурирование приложений
- •2.6. Задание ссылок на ресурсы
- •4. Введение в компоненты Facelets
- •4.1. Веб-страницы
- •4.2. Разработка простого приложения Facelets
- •4.3. Использование шаблонов
- •5. Унифицированный язык записи выражений
- •6.1. Добавление компонент библиотеки HTML на страницу
- •6.2. Использование компонент для таблиц баз данных
- •6.3. Использование тегов библиотеки Core
- •7. Использование конвертеров, слушателей и проверок
- •7.1. Использование стандартных преобразователей
- •7.2. Регистрация слушателей для компонентов
- •8. Внешние объекты (JavaBeans)
- •8.1. Создание класса внешних объектов
- •8.2. Описание свойств бинов
- •8.3. Написание методов внешних бинов
- •8.4. Проверка бинами
- •9.1. Файл конфигурации ресурсов приложения
- •9.2. Упорядочение ресурсов конфигурации приложения
- •9.3. Конфигурирование состояния проекта
- •9.4. Выбор конфигурации бина
- •9.5. Регистрация сообщений об ошибках как пакет ресурса
- •9.7. Конфигурирование правил навигации (Navigation Rules)
- •9.8. Основные требования приложения JavaServer Faces
- •10. Технология Java Servlet
- •11. Введение в Java Persistence API
- •11.1. Требования к классам сущностей
- •11.3. Внедряемые классы в сущностях
- •11.4. Наследование сущностей
- •11.5. Стратегии наследования сущностей с отображением
- •11.6. Управление сущностями
- •11.7. Запросы сущностей
- •12. Примеры хранимых сущностей
- •12.1. Приложение order
- •12.2. Пример получения схемы отношений на основе таблиц БД
- •13.1. Терминология языка запросов
- •13.3. Упрощенный синтаксис языка запросов
- •13.4. Примеры запросов
- •13.5. Запросы с навигацией связанных сущностей
- •13.6. Запросы с другими условными выражениями
- •13.7. Изменение и удаление группы сущностей
- •13.8. Полный синтаксис языка запросов
- •14. Язык запросов Criteria API
- •14.3. Корни запроса
- •14.4. Использование объединения в запросе
- •14.5. Навигация путей в запросах
- •14.6. Ограничения на результаты запроса
- •14.7. Управление результатами запросов
- •14.8. Исполнение запросов
- •15. Связывание ресурсов
- •15.1. Ресурсы и служба имен JNDI
- •15.2. Объекты DataSource и пулы соединений (Connection Pools)
- •15.3. Внедрение ресурсов
- •15.4. Адаптеры ресурсов
- •15.5. Аннотации метаданных
- •16. Безопасность веб-приложений
- •16.1. Краткий обзор
- •16.2. Механизмы обеспечения безопасности
- •16.3. Безопасность сервера предприятия
- •16.4. Использование защищенного соединения SSL
- •18. Пример приложения
- •18.1. Создание проекта веб-приложения
- •18.3.Структура приложения JavaEE 6
- •18.4. Программирование вида для объектов
- •18.5. Дизайн главной страницы
- •18.6. Страница просмотра записей таблицы городов
- •18.7. Страница добавления записей о городах
- •18.8. Страница редактирования записей о городах
- •18.9. Страница удаления записей о городах
- •19. Обработка связей внешних ключей
- •19.1. Разработка класса для вида сущности
- •19.2. Доработка вида для городов
- •19.3. Разработка обзорной страницы
- •19.5. Страница для редактирования записей с внешними ключами
- •20. Дополнительные функции
- •20.1. Сортировка записей таблицы
- •20.2. Контроль за удалением связанных записей
- •20.3. Контроль ввода наименований
- •20.4. Запросы к БД на языке Java Persistence Query Language
- •20.5. Управление страницами при просмотре таблицы
- •20.6. Создание и просмотр отчетов
- •20.7. Использование шаблонов и стилей
- •20.8. Защита приложения паролем
- •Заключение
- •Библиографический список
глубоких иерархий классов. Аналогичным образом запросы, которые покрывают всю иерархию класса, требуют операции присоединения между таблицами подклассов, в результате чего снижается скорость исполнения.
Некоторые поставщики Java Persistence API, включая поставщика «по умолчанию» Enterprise Server, требуют задания столбца дискриминатора в таблице, соответствующего корневой сущности при использовании стратегии присоединения подкласса. Если вы не используете автоматическое создание таблиц в вашем приложении, убедитесь, что база данных правильно устанавливает для столбца таблицы дискриминатора значение по умолчанию или использует аннотацию @DiscriminatorColumn, чтобы соответствовать схеме вашей базы данных.
11.6. Управление сущностями
Сущностные экземпляры управляются менеджером сущностей. Менеджер сущностей представлен экземпляром класса javax.persistence.EntityManager. Каждый экземпляр EntityManager связан с контекстом хранения. Контекст хранения определяет область, в которой конкретные экземпляры сущности созданы, хранятся и удаляются.
Контекст хранения является множеством управляемых экземпляров сущностей, которое существует в конкретном хранилище данных.
Интерфейс EntityManager
Интерфейс EntityManager определяет методы для взаимодействия с контекстом хранения. EntityManager API создает и удаляет хранимые экземпляры сущности, находит объекты по первичному ключу и выполняет запросы объектов.
Container-Managed Entity Managers
Управляемый контейнерным менеджером сущностей контекст хранения экземпляра EntityManager автоматически распространяется контейнером на все прикладные компоненты, которые используют экземпляр EntityManager в пределах одной транзакции Java Transaction Architecture (JTA) .
Транзакции JTA обычно включают вызовы через прикладные компоненты. Для того чтобы завершать транзакции JTA, этим компонентам, как правило, нужен доступ к одному контексту хранения. Это происходит тогда, когда EntityManager внедряют в прикладные компоненты посредством аннотации javax.persistence.PersistenceContext. Контекст хранения автоматически распространяется на текущую транзакцию JTA и транзакцииEntityManager,чтоотображенынатотжемодульхранения,иобеспечивают доступ к контексту хранения в пределах этой транзакции. Автоматически распространяя контекст хранения, прикладным компонентам не нужно передавать транзакции экземпляра EntityManager друг другу для того, чтобы делать изменения в пределах транзакции. Контейнер Java EE управляет циклом жизни управляющих менеджеров сущностей.
Для того чтобы получать экземпляр EntityManager, внедрите менеджер сущностей в прикладной компонент:
@PersistenceContext EntityManager em;
С другой стороны, менеджеры сущностей приложения не распространяют контекст хранения на прикладные компоненты, и цикл жизни экземпляров EntityManager управляется приложением.
123
Менеджеры сущностей приложения используются приложением, когда нужно иметь доступ к контексту хранения, который не распространяется транзакцией 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();
Менеджеры объектов приложения не распространяют автоматически контекст
транзакции JTA. Таким приложениям необходимо вручную получать доступ к менеджеру транзакции JTA и добавлять ограничения транзакции при выполнении операций
с сущностями. Интерфейс javax.transaction.UserTransaction определяет методы для
начала, завершения и отмены транзакции. Внедрите экземпляр UserTransaction, создавая переменную экземпляра, аннотированную @Resource.
@Resource UserTransaction utx;
Для того чтобы начать транзакцию, вызовите метод UserTransaction.begin. Когда все операции объекта завершатся, вызовите метод UserTransaction.commit, чтобы завершить транзакцию. Метод UserTransaction.rollback используется для отмены текущей транзакции.
Следующий пример показывает, как управлять транзакциями в приложении, которое использует прикладной менеджер сущностей.
@PersistenceContext 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();
}
124
Поиск сущностей с использованием EntityManager
Метод EntityManager.find используется для поиска сущностей с заданным пер-
вичным ключом.
@PersistenceContext EntityManager em;
public void enterOrder(int custID, Order newOrder) { Customer cust = em.find(Customer.class, custID); cust.getOrders().add(newOrder); newOrder.setCustomer(cust);
}
Управление жизненным циклом экземпляра сущности
Вы управляете экземплярами сущности, выполняя операции на объекте мето-
дами экземпляра EntityManager. Экземпляры сущности находятся в одном из четырех
состояний: новый, управляемый, отделенный или удаленный.
Новые экземпляры сущности не имеют хранимого образа и еще не связаны
контекстом хранения.
Управляемые экземпляры сущности имеют хранимый образ и связаны контек-
стом хранения.
Отделенные экземпляры сущности имеют хранимый образ и к настоящему времени не связаны контекстом хранения.
Удаленные экземпляры сущности имеют хранимый образ, связаны контекстом хранения и запланированы для удаления из хранилища данных.
Хранимые экземпляры сущности
Новые экземпляры сущности становятся управляемыми и хранимыми вызовом
метода persist или каскадной операцией persist, вызванной связанной сущностью, имеющей элементы cascade=PERSIST или cascade=ALL в аннотации отношения. Это означает, что данные сущности загружаются в базу данных, когда завершается тран-
закция, связанная с операцией хранения. Если сущности уже управляемые, операция хранения игнорируется, хотя операция persist будет выполнена каскадно для связанных объектов, которые имеют элемент cascade, установленный в PERSIST или ALL в аннотации отношения. Если persist вызван удаленным экземпляром сущности, он становится управляемым. Если сущность отделена, persist возбудит исключение IllegalArgumentException, или завершение транзакции потерпит неудачу.
@PersistenceContext EntityManager em;
...
public LineItem createLineItem(Order order, Product product, int quantity) {
LineItem li = new LineItem(order, product, quantity); order.getLineItems().add(li);
em.persist(li); return li;
}
125
Операция persist распространится на все сущности, имеющие отношение к вы-
зывающей сущности, у которых установлен элемент cascade в ALL или PERSIST в
аннотации отношения.
@OneToMany(cascade=ALL, mappedBy="order") public Collection<LineItem> getLineItems() {
return lineItems;
}
Удаление экземпляров сущности
Управляющие экземпляры сущности удаляются вызовом метода remove
или каскадной операцией удаления со связанных объектов, имеющих элементы cascade=REMOVE или cascade=ALL в аннотации отношения. Если метод удаления remove вызван для новой сущности, операция удаления игнорируется, хотя remove
будет выполняться каскадно для связанных сущностей, которые имеют cascade-
элемент REMOVE или ALL в аннотации отношения. Если удаление выполняется для
отделённой сущности, оно возбудит исключение IllegalArgumentException, или завер-
шение транзакции потерпит неудачу. Если удаление выполняется для уже удаленной
сущности, оно будет проигнорировано. Данные будут удалены из хранилища, когда
завершается транзакция или в результате операции flush.
public void removeOrder(Integer orderId) { try {
Order order = em.find(Order.class, orderId); em.remove(order);
}...
В этом примере все сущности LineItem, связанные с заказом, также удалены, так как Order.getLineItems был установлен в cascade=ALL в аннотации отношения.
Синхронизация данных сущности в базе данных
Состояние хранимых сущностей синхронизируется в базе данных, когда транзакция, с которой связаны сущности, подтверждается. Если управляющая сущность
связана двунаправленным отношением с другим управлявшим объектом, данные будут сохранены на собственной стороне отношения.
Для того чтобы форсировать синхронизацию управляющего объекта в хранилище данных, вызовите метод flush экземпляра EntityManager. Если сущность обу-
словливается другой сущностью, и в аннотации отношения был установлен каскадный
элемент в PERSIST или ALL, связанные данные сущности будут синхронизированы с хранилищем данных, когда вызывается метод flush.
Если объект удален, вызов flush удалит данные сущности из хранилища данных.
Модуль хранения
Модульхраненияопределяетмножествовсехклассовсущности,которыеуправляются экземплярами EntityManager в приложении. Это множество классов сущностей представляет хранилище данных.
Модули хранения определены файлом конфигурации persistence.xml. Файл JAR или директория, чья директория МЕТА-INF содержит persistence.xml, называется
корнем модуля хранения. Область видимости модуля хранения определена корнем
хранилища.
126
Каждый модуль хранения должен называться уникальным именем в области
видимости.
Модули хранения могут быть упакованы как часть файла WAR или EJB JAR,
или же как файл JAR, который затем может быть включен в файл WAR или EJB JAR.
Если вы упаковываете модуль хранения как множество классов в файле EJB
JAR, persistence.xml должен быть вложен в папку META-INF архива EJB JAR.
Если вы упаковываете модуль хранения как множество классов в WAR-файле, persistence.xml должен быть расположен в папке WEB-INF/classes/META-INF.
Если вы упаковываете модуль хранения в файл JAR, который будет включен в файл WAR или EAR , то файл JAR должен быть расположен:
•в WEB-INF/lib архива WAR;
•в папке библиотек /lib файла EAR .
Примечание. В Java Persistence API 1.0 файлы JAR могли быть располо-
жены в корне файла EAR как корень устройства хранения. Эта возможность устарела и больше не поддерживается. Портируемые приложения
должны использовать библиотечную директорию /lib файла EAR как корень модуля хранения.
Файл persistence.xml
Файл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.Order</class> <class>com.widgets.Customer</class>
</persistence-unit> </persistence>
Этот файл определяет модуль хранения с именем OrderManagement, которое
использует JTA – источник данных jdbc/MyOrderDB. Элементы jar-file и class определяют управляемые классы хранения: классы сущности, embeddable-классы и отображающие суперклассы. Элемент jar-file определяет файлы архива, которые видимы на упакованном устройстве хранения, содержащем классы хранения. Элемент class явно
называет хранимые классы.
Элементы jta-data-source (для источников данных JTA) и non-jta-data-source
(не источники данных JTA) определяют глобальное имя JNDI источника данных, кото-
рое использует контейнер.
127