- •Обозначения и сокращения
- •введение
- •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. Защита приложения паролем
- •Заключение
- •Библиографический список
Удаление сущностей
Бизнес-метод RequestBean.removeOrder удаляет данный заказ из базы данных.
Он использует метод EntityManager.remove, чтобы удалить сущности из базы данных.
Order order = em.find(Order.class, orderId); em.remove(order);
12.1.4. Построение и прогон приложения order
Формирование, упаковка, развертывание и выполнение в NetBeans IDE
Чтобы формировать, упаковывать, развертывать и запускать пример заказа на
вашем сервере предприятия в NetBeans IDE, следуйте этим инструкциям:
1.В NetBeans IDE выберите File>Open Project.
2.В открытом диалоге проекта перейдите в tut-install/examples/persistence/.
3.Выберите папку order.
4.Выберите переключатель Open as Main Project.
5.Откройте проект.
6.В закладке проектов правым щелчком выберите проект order и Run.
NetBeans откроет окно веб-браузера http://localhost:8080/order/.
Формирование, упаковка, развертывание и выполнение в Ant
Чтобы сформировать прикладные компоненты order, введите команду: ant
Она выполняет по умолчанию задачу, которая компилирует исходные файлы и упаковывает приложение в WAR-файл, расположенный в tut-install/examples/persis- tence/order/dist/order.war.
Для того чтобы развернуть WAR, убедитесь что сервер запущен, затем введите
следующую команду: ant deploy
Откройте окно просмотра веб в http://localhost:8080/order/, чтобы создавать и корректировать данные заказа.
Задача All
По соглашению, задача all сформирует, упакует, развернет и запустит приложение. Для того чтобы сделать это, введите команду:
ant all
Удаление приложения
Для удаления приложения order.war введите следующую команду: ant undeploy
12.2.Пример получения схемы отношений на основе таблиц БД
Средствами NetBeans IDE можно получить объявления сущностей для использования в Java EE 6 на основе имеющихся таблиц базы данных.
Для этого необходимо объявить ресурсный пул и ресурс, соответствующие имеющейся СУБД и базе данных, подключенным к проекту веб-приложения. Далее на закладке проектов выбрать папку проекта с расширением ejb, правой кнопкой щелкнуть по имени папки и выбрать пункт меню «Создать – Классы сущностей из базы данных».
138
Служба NetBeans IDE произведет анализ имеющихся таблиц базы данных и построит бины с необходимыми описаниями свойств и аннотаций.
Следующие таблицы созданы в СУБД Postgresql приведёнными ниже операто-
рами.
--Рудные тела
--1) Идентификатор (ПК)
--2) Горизонт (ВК)
--3) Высота слоя, м
--4) Сорт (ВК)
--Table: body
--DROP TABLE body;
CREATE TABLE body
(
id_body serial NOT NULL, id_hor integer NOT NULL,
h_body numeric(4,2) NOT NULL DEFAULT 10, id_sort integer NOT NULL,
CONSTRAINT "PK_body" PRIMARY KEY (id_body), CONSTRAINT "FK_body_hor" FOREIGN KEY (id_hor)
REFERENCES horizons (id_hor) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT "FK_body_sort" FOREIGN KEY (id_sort) REFERENCES sorts (id_sort) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH ( OIDS=FALSE
);
ALTER TABLE body OWNER TO cyx;
COMMENT ON TABLE body IS 'Рудные тела (главная)';
------------------------------------------------
--Список фрагментов рудного тела
--1) Идентификатор (ПК)
--2) Рудное тело (ВК)
--3) Фрагмент (ВК)
--Table: body_frag
--DROP TABLE body_frag;
CREATE TABLE body_frag
(
id_body_frag serial NOT NULL, id_body integer NOT NULL, id_frag integer NOT NULL,
CONSTRAINT "PK_fr_body" PRIMARY KEY (id_body_frag), CONSTRAINT "FK_body_fr" FOREIGN KEY (id_frag)
139
REFERENCES fragments (id_fragment) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT "FK_id_body" FOREIGN KEY (id_body) REFERENCES body (id_body) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH ( OIDS=FALSE
);
ALTER TABLE body_frag OWNER TO cyx;
COMMENT ON TABLE body_frag IS 'Фрагменты рудных тел';
------------------------------------------------
--Характеристика тела
--1) Идентификатор (ПК)
--2) Тело (ВК)
--3) Параметр (ВК)
--4) Значение, веществ
--Table: body_char
--DROP TABLE body_char;
CREATE TABLE body_char
(
id_body_char serial NOT NULL, id_body integer NOT NULL, id_par integer NOT NULL, "value" real NOT NULL,
CONSTRAINT "PK_body_char" PRIMARY KEY (id_body_char), CONSTRAINT "FK_body_id" FOREIGN KEY (id_body)
REFERENCES body (id_body) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT "FK_body_par" FOREIGN KEY (id_par)
REFERENCES params (id_param) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH ( OIDS=FALSE
);
ALTER TABLE body_char OWNER TO cyx;
COMMENT ON TABLE body_char IS 'Характеристики тела';
Логическая модель фрагмента базы данных приведена на рис. 12.1.
После получения схемы будем иметь следующие описания бинов (по тексту кур-
сивом добавлены комментарии к сгенерированным текстам программ на языке Java). package ggis_ejb;
// Раздел импорта стандартных пакетов и классов import java.io.Serializable;
140
Рис. 12.1. Логическая схема данных
import java.math.BigDecimal; import java.util.Collection; import javax.persistence.Basic;
import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id;
import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.OneToMany; import javax.persistence.Table;
//Аннотации для объявления класса для сущности "Рудные тела"
@Entity
@Table(name = "body")
//Именованные запросы для трех вариантов
@NamedQueries({
@NamedQuery(name = "Body.findAll", query = "SELECT b FROM Body
b"),
@NamedQuery(name = "Body.findByIdBody", query = "SELECT b FROM Body b WHERE b.idBody = :idBody"),
@NamedQuery(name = "Body.findByHBody", query = "SELECT b FROM Body b WHERE b.hBody = :hBody")})
// Объявление класса для сущности "Рудные тела" public class Body implements Serializable {
141
// Ключ сериализации
private static final long serialVersionUID = 1L;
//Первичный ключ
@Id
@Basic(optional = false) @Column(name = "id_body") private Integer idBody;
//Свойство "Высота слоя"
@Basic(optional = false) @Column(name = "h_body") private BigDecimal hBody;
//Внешний ключ на таблицу "Горизонты" аннотируется @JoinColumn
и@ManyToOne
@JoinColumn(name = "id_hor", referencedColumnName = "id_hor") @ManyToOne(optional = false)
private Horizons idHor;
//Внешний ключ на таблицу "Сорта" аннотируется @JoinColumn
и@ManyToOne
@JoinColumn(name = "id_sort", referencedColumnName = "id_sort")
@ManyToOne(optional = false) private Sorts idSort;
//Из таблицы "Характеристика тела" есть ВК на таблицу "Рудные
тела"
@OneToMany(cascade = CascadeType.ALL, mappedBy = "idBody") private Collection<BodyChar> bodyCharCollection;
//Из таблицы "Список фрагментов" есть ВК на таблицу "Рудные
тела"
@OneToMany(cascade = CascadeType.ALL, mappedBy = "idBody") private Collection<BodyFrag> bodyFragCollection;
//Конструкторы сущностей "Рудные тела"
public Body() {
}
public Body(Integer idBody) { this.idBody = idBody;
}
public Body(Integer idBody, BigDecimal hBody) { this.idBody = idBody;
this.hBody = hBody;
}
142
//Методы доступа к свойствам сущностей "Рудные тела"
//Метод get
public Integer getIdBody() { return idBody;
}
// Метод set
public void setIdBody(Integer idBody) { this.idBody = idBody;
}
public BigDecimal getHBody() { return hBody;
}
public void setHBody(BigDecimal hBody) { this.hBody = hBody;
}
public Horizons getIdHor() { return idHor;
}
public void setIdHor(Horizons idHor) { this.idHor = idHor;
}
public Sorts getIdSort() { return idSort;
}
public void setIdSort(Sorts idSort) { this.idSort = idSort;
}
// Доступ к коллекции сущностей "Характеристика тела" в отно-
шении ManyToOne
public Collection<BodyChar> getBodyCharCollection() { return bodyCharCollection;
}
public void setBodyCharCollection(Collection<BodyChar> bodyCharCollection) {
this.bodyCharCollection = bodyCharCollection;
}
// Доступ к коллекции сущностей "Список фрагментов" в отноше-
нии ManyToOne
public Collection<BodyFrag> getBodyFragCollection() { return bodyFragCollection;
143
}
public void setBodyFragCollection(Collection<BodyFrag> bodyFragCollection) {
this.bodyFragCollection = bodyFragCollection;
}
// Метод вычисления хеш-функции для упаковки сущностей
@Override
public int hashCode() { int hash = 0;
hash += (idBody != null ? idBody.hashCode() : 0); return hash;
}
//Метод сравнения двух сущностей
@Override
public boolean equals(Object object) {
//TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Body)) { return false;
}
Body other = (Body) object;
if ((this.idBody == null && other.idBody != null) || (this.idBody != null && !this.idBody.equals(other.idBody))) {
return false;
}
return true;
}
//Метод преобразования в строку
@Override
public String toString() {
return "ggis_ejb.Body[idBody=" + idBody + "]";
}
}
// Класс характеристик тел
package ggis_ejb;
import java.io.Serializable; import javax.persistence.Basic; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id;
import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.Table;
144
// Аннотации для объявления класса для сущности "Характеристика тела"
@Entity
@Table(name = "body_char") @NamedQueries({
@NamedQuery(name = "BodyChar.findAll", query = "SELECT b FROM BodyChar b"),
@NamedQuery(name = "BodyChar.findByIdBodyChar", query = "SELECT b FROM BodyChar b WHERE b.idBodyChar = :idBodyChar"),
@NamedQuery(name = "BodyChar.findByValue", query = "SELECT b FROM BodyChar b WHERE b.value = :value")})
// Объявление класса для сущности «Характеристика тела» public class BodyChar implements Serializable {
private static final long serialVersionUID = 1L;
//Первичный ключ
@Id
@Basic(optional = false) @Column(name = "id_body_char") private Integer idBodyChar;
//Поле значения
@Basic(optional = false) @Column(name = "value") private float value;
//Внешний ключ на таблицу "Рудное тело" аннотируется
@JoinColumn и @ManyToOne
@JoinColumn(name = «id_body», referencedColumnName = "id_body")
@ManyToOne(optional = false) private Body idBody;
//Внешний ключ на таблицу "Параметры" аннотируется @JoinColumn
и@ManyToOne
@JoinColumn(name = "id_par", referencedColumnName = "id_param")
@ManyToOne(optional = false) private Params idPar;
// Конструкторы сущности "Характеристика тела" public BodyChar() {
}
public BodyChar(Integer idBodyChar) { this.idBodyChar = idBodyChar;
}
public BodyChar(Integer idBodyChar, float value) { this.idBodyChar = idBodyChar;
this.value = value;
}
145
// Методы доступа к свойствам сущностей "Характеристика тела" public Integer getIdBodyChar() {
return idBodyChar;
}
public void setIdBodyChar(Integer idBodyChar) { this.idBodyChar = idBodyChar;
}
public float getValue() { return value;
}
public void setValue(float value) { this.value = value;
}
public Body getIdBody() { return idBody;
}
public void setIdBody(Body idBody) { this.idBody = idBody;
}
public Params getIdPar() { return idPar;
}
public void setIdPar(Params idPar) { this.idPar = idPar;
}
// Вспомогательные методы для упаковки, сравнения и печати
@Override
public int hashCode() { int hash = 0;
hash += (idBodyChar != null ? idBodyChar.hashCode() : 0); return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof BodyChar)) { return false;
}
BodyChar other = (BodyChar) object;
if ((this.idBodyChar == null && other.idBodyChar != null) || (this.idBodyChar != null && ! this.idBodyChar.equals(other.idBodyChar))) {
146
return false;
}
return true;
}
@Override
public String toString() {
return "ggis_ejb.BodyChar[idBodyChar=" + idBodyChar + "]";
}
}
package ggis_ejb;
import java.io.Serializable; import javax.persistence.Basic; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id;
import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.Table;
// Аннотации для объявления класса для сущности "Фрагменты тела"
@Entity
@Table(name = "body_frag") @NamedQueries({
@NamedQuery(name = "BodyFrag.findAll", query = "SELECT b FROM BodyFrag b"),
@NamedQuery(name = "BodyFrag.findByIdBodyFrag", query = "SELECT b FROM BodyFrag b WHERE b.idBodyFrag = :idBodyFrag")})
public class BodyFrag implements Serializable { private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false) @Column(name = "id_body_frag") private Integer idBodyFrag;
@JoinColumn(name = "id_body", referencedColumnName = "id_body")
@ManyToOne(optional = false) private Body idBody;
@JoinColumn(name = "id_frag", referencedColumnName = "id_fragment")
147
@ManyToOne(optional = false) private Fragments idFrag;
public BodyFrag() {
}
public BodyFrag(Integer idBodyFrag) { this.idBodyFrag = idBodyFrag;
}
public Integer getIdBodyFrag() { return idBodyFrag;
}
public void setIdBodyFrag(Integer idBodyFrag) { this.idBodyFrag = idBodyFrag;
}
public Body getIdBody() { return idBody;
}
public void setIdBody(Body idBody) { this.idBody = idBody;
}
public Fragments getIdFrag() { return idFrag;
}
public void setIdFrag(Fragments idFrag) { this.idFrag = idFrag;
}
@Override
public int hashCode() { int hash = 0;
hash += (idBodyFrag != null ? idBodyFrag.hashCode() : 0); return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof BodyFrag)) { return false;
}
BodyFrag other = (BodyFrag) object;
if ((this.idBodyFrag == null && other.idBodyFrag != null) || (this.idBodyFrag != null && ! this.idBodyFrag.equals(other.idBodyFrag))) {
148
return false;
}
return true;
}
@Override
public String toString() {
return "ggis_ejb.BodyFrag[idBodyFrag=" + idBodyFrag + "]";
}
}
Общие правила установления соответствия между таблицами классических ре-
ляционных баз данных и сущностями в Java EE 6 можно сформулировать следующим образом.
1.Каждая таблица имеет собственный класс сущностей.
2.Класс сущности имеет аннотации для задания хранимой таблицы БД:
@Entity
@Table(name = "body")
где body – имя таблицы.
3.Для поиска записей в текст включаются аннотации создания именованных
запросов к таблице: поиск всех записей, поиск записи по ключу, поиск по
полю данных.
4.Класс сущности реализует интерфейс сериализации с необходимым ключом и методами:
public class Body implements Serializable {
// Ключ сериализации
private static final long serialVersionUID = 1L;
@Override
public int hashCode() {
. . .
}
@Override
public boolean equals(Object object) {
. . .
}
@Override
public String toString() {
. . .
}
}
5. Первичный ключ имеет аннотации:
@Id
@Basic(optional = false) @Column(name = "id_body") private Integer idBody;
149
6. Простое поле имеет аннотации:
@Basic(optional = false) @Column(name = "h_body") private BigDecimal hBody;
7. Внешний ключ имеет аннотации
@JoinColumn(name = "id_hor", referencedColumnName = "id_hor") @ManyToOne(optional = false)
private Horizons idHor;
8. Класс имеет конструкторы без параметров и с параметрами:
public Body() {
}
public Body(Integer idBody) { this.idBody = idBody;
}
public Body(Integer idBody, BigDecimal hBody) { this.idBody = idBody;
this.hBody = hBody;
}
9.Если на сущность есть ссылки внешнего ключа из другой таблицы, то класс имеет свойство – коллекцию с методами доступа:
@OneToMany(cascade = CascadeType.ALL, mappedBy = "idBody") private Collection<BodyChar> bodyCharCollection;
public Collection<BodyChar> getBodyCharCollection() { return bodyCharCollection;
}
public void setBodyCharCollection(Collection<BodyChar> bodyCharCollection) {
this.bodyCharCollection = bodyCharCollection;
}
150