Пояснительная записка к диплому (1228397), страница 7
Текст из файла (страница 7)
(
ID_operation serial primary key,
date_operation date,
exeqution_time_days int,
initiator int8 unsigned,
foreign key(initiator) references Workers(ID_worker) ON DELETE set null,
shift_worker int8 unsigned,
foreign key(shift_worker) references Workers(ID_worker) ON DELETE set null,
warehouse_of_plus int8 unsigned,
foreign key(warehouse_of_plus) references Warehouses_info(ID_warehouse) ON DELETE set null,
warehouse_of_minus int8 unsigned,
foreign key(warehouse_of_minus) references Warehouses_info(ID_warehouse) ON DELETE set null,
operation_type int8 unsigned,
foreign key(operation_type) references Operation(ID_operation_type) ON DELETE set null,
number_of_units int,
affected_units int8 unsigned,
foreign key(affected_units) references UnitsInWarehouse(ID_record) ON DELETE set null,
comments text
);
Стоит заметить, что поля, указанные как внешние ключи, имеют числовой тип, это связано с рекомендацией устанавливать в качестве первичных ключей числовые значения, поэтому внешний ключ также является простым числом. Код для создания остальных таблиц строится по аналогии и рассматриваться не будет.
Далее следует описать способ заполнения таблицы данными, для вставки записи в таблицу в MySQL используется следующая запись:
insert into TABLE(…) value(Запись1),(Запись2),…
Где Запись1 и Запись 2 представляют собой набор значений указанных в скобках параметров для вставки двух новых записей. Таким образом для вставки в таблицу журнала операций записи следует использовать следующий код:
insert into OperationJournal(date_operation, exeqution_time_days, initiator, shift_worker, warehouse_of_plus, warehouse_of_minus, operation_type, number_of_units, affected_units)
value ('2015-05-12',5,1,2,3,2,1,6,2);
Приведённый выше код создаст запись в журнале операций со следующими параметрами:
– дата операции – 12 мая 2015;
– срок выполнения (в днях) – 5 дней;
– инициатор – ссылка на сотрудника с идентификатором равным 1;
– дежурный рабочий – ссылка на сотрудника с идентификатором 2;
– склад прибытия – ссылка на склад из журнала складов с идентификатором 3;
– склад убытия – ссылка на склад из журнала складов с идентификатором 2;
– тип операции – ссылка на запись таблицы виды операций с идентификатором 1;
– количество затронутых единиц – 6 шт;
– связанная запись из журнала учёта единиц товара имеет идентификатор 2.
Следует заметить, что указанный выше код сработает только в случае существования связанных таблиц и в случае наличия в них записей с первичными ключами указанных как внешние ключи.
Для остальных таблиц заполнение записями будет иметь код сформированный по тому же принципу, в связи с этим код для заполнения их не будет рассматриваться.
Таким образом была создана и заполнена данными база данных для последующего использования в АРМ. Далее следует перейти к непосредственной разработке элементов АРМ.
3.2 Подготовка к разработке АРМ
Ранее осуществлено проектирование общей архитектуры программного обеспечения в модульном виде, однако каждая конкретная реализация MVC по-своему может организовывать внутреннюю структуру блоков. Реализация MVC в JSF представлена на рисунке 1.
Рисунок 1 – Реализация MVC в JSF
Для начала следует рассмотреть набор представлений JSF осуществляющих отображение данных для пользователя. В общем случае рекомендуется реализовывать четыре представления для каждой сущности, каждое ответственно за конкретную операцию. В типовой блок разрабатываемого приложения войдут следующие представления:
– просмотр списка записей или поискового запроса по таблице;
– редактирование/просмотр выбранной записи;
– добавление новой записи;
– поисковая форма.
Для управления этими представлениями используется один контроллер – контроллер представления. Он в свою очередь связывается с другим контроллером – контроллером фасада модели, который ответственен за связь с моделью, хранящей информацию о сущности. В контроллере представлений осуществляется ссылка на реализацию каждого из методов, соответствующих операциям на представлениях, описанных в контроллере фасада модели [15].
Таким образом типовой блок, в разрабатываемом приложении, имеет следующий состав:
– четыре представления для просмотра списка записей, просмотра/редактирования записи, поисковую форму, добавления записи;
– контроллер представления, для связи с моделью через контроллер фасада модели;
– контроллер фасада модели, для инкапсуляции и определения функций взаимодействия с моделью;
– модель, хранящая в себе данные сущности, полученные по запросу из базы данных.
Стоит также упомянуть, что работа с базой данных осуществляется при помощи JPA. Благодаря данной технологии разработчик избавляется от необходимости управлять SQL запросами вручную, эта обязанность возлагается на язык запросов JPA – JPQL, запросы которого напрямую зависят от подготовленной модели и их результаты также привязаны к конкретной модели, что значительно упрощает работу с созданной моделью [16].
Помимо указанных выше элементов в состав типового блока также могут входить обработчики исключений, возникающих в ходе работы приложения с данным блоком, а также различные специальные компоненты, такие как обработчик постраничной навигации и т.д.
Теперь следует рассмотреть содержимое конкретных классов, входящих в типовой блок. Так, например, в модели следует хранить в защищённом виде все поля из сущности соответствующей журналу информации о складах, а также предоставлять методы доступа к этим полям и функцию перевода записи в строку для отображения в различных списках. Контроллер фасада модели должен содержать в себе методы для выборки данных, редактирования и подсчёта записей. Контроллер представления в свою очередь должен содержать в себе методы адресации, содержащие логику которая должна быть выполнена при переходе между представлениями, методы обрабатывающие операции редактирования и поиска данных, а также механизм обеспечивающий возможность постраничной навигации.
Все блоки строятся по одному принципу, но с поправками на реализуемый функционал, поэтому в качестве примера построения блока рассмотрен блок адресов, реализующий все составные элементы типового блока, описанные выше, а также являющийся довольно простым для понимания и описания.
3.3 Разработка основных элементов АРМ
Для начала следует выполнить разработку основных элементов АРМ – моделей, контроллеров и элементов необходимых для их функционирования. Для реализации использован язык программирования Java. Для работы с базой данных использован JPA. Разработка основных элементов будет осуществляться по блокам, выделенным на этапе проектирования. В качестве примера будет выполнена разработка блока ответственного за информацию об адресах.
Для начала следует определить единицу постоянства (persistence unit) для того чтобы у приложения была возможность обращаться к базе данных с использованием JPA, для этого в каталоге приложения создаётся файл persistence.xml в папке с файлами конфигурации после чего в этом необходимо написать подключение библиотек для функционирования единицы постоянства и определить её имя, источник данных (схема базы данных в созданная ранее в MySQL) и, при необходимости задать дополнительные параметры. Настроенная единица постоянства будет выглядеть следующим образом:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="AutomatedWorkPlace" transaction-type="JTA">
<jta-data-source>AWPoWW</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties/>
</persistence-unit>
</persistence>
После задания единицы постоянства следует создать модель для хранения адресов.
3.3.1 Создание моделей
Модель будет содержать в себе те же поля что и таблица в базе данных, которые будут иметь соответствующий тип данных. Согласно стандартам языка Java начинаться класс модели должен с объявления пакета, к которому принадлежит данный класс. В случае с моделями, пакет, в котором они будут храниться будет назван models. Также для того чтобы дать компилятору понять, что он работает с моделью нужно сделать следующее объявление @Entity, тогда компилятор будет интерпретировать этот класс как сущность базы данных, что необходимо на более низком уровне для корректного взаимодействия с контроллером фасада модели и в целом интерпретации данного класса. Помимо этого, необходимо добавить объявление @Table с названием таблицы на основе которой строится модель, это укажет на таблицу из источника данных отражением которой в программе является данная сущность [17]. Также классу модели (как и контроллеру представления) необходимо реализовывать интерфейс сериализации (serializable), встроенного механизма хранения объектов в Java и добавить поле версии серии для этого механизма [18].
Помимо этого, для корректного программного представления перед полями класса нужно указывать объявление @Column с указанием столбца таблицы отражением, которого является данное поле. Для первичного ключа помимо объявления @Column требуется также объявление @Id, для него же необходимо использовать объявление @GeneratedValue, для определения стратегии генерации первичного ключа. Также в таблице присутствуют внешние ключи, а для их записи в JPA требуется указывать объявление @JoinColumn с указанием поля, которое является внешним ключом и поля которое ставится ему в соответствие [17]. Поле, в которое помещается присоединённое значение должно иметь тип класса модели, к которой относится присоединяемое поле. Стоит заметить, что все поля класса модели согласно принципу инкапсуляции объектно-ориентированного программирования должны быть инкапсулированы, т.е. помещены в защищённую область памяти из которой доступ к ним получить может только экземпляр класса родителя. Это же правило действительно и для всех остальных классов, включая контроллеры. Также могут быть указаны и другие объявления для обозначения ограничений на поле, создания именованных запросов. Также в модели требуется перегрузить функции сравнения, преобразования в строку и получения хеш-кода, для возможности обработки в связанных контроллерах.
Метод перевода в строку перегружается таким образом, чтобы возвращать строковое представление и по сути краткое описание конкретной записи таблицы адресов, для этого вполне подойдёт конкатенация полей город, улица и дом. В некоторых ситуациях будут требоваться также метод сравнения. Этот метод автоматически вызывается в определённых ситуациях требующих сравнения записей или проверки принадлежности некоторого объекта типу сущности адресов. Для успешной работы метода сравнения требуется также перегрузить Метод получения хеш-кода просто возвращает значение, полученное как результат выполнения соответствующего метода типа Long, который генерирует хеш-код на основе идентификатора сущности [19].
После описания полей и перегруженных функций, необходимо задать методы установки и получения значений для инкапсулированных полей, для наличия возможности работы с моделью из других классов. В общем случае метод получения значения выглядит следующим образом:
public FiledType getField() {
return field;
},
где FiledType – тип поля для которого пишется метод, а field само поле для которого он пишется.
Метод установки значения в общем случае выглядит следующим образом:
public void setField(FiledType ValueToSet) {
this.field = ValueToSet;
},
где ValueToSet – значение которое нужно установить для данного поля.
После этого остаётся только задать конструктор по умолчанию и конструктор с параметром. Конструктор по умолчанию оставляется пустым, в то время как в конструкторе с параметром производится установка параметра в некоторое поле класса, как правило в качестве поля для установки выбирается первичный ключ.
Также стоит упомянуть что для корректной работы вышеописанных объявлений и следует выполнить импорт пакетов, к которым они относятся. Импорт пакетов лучше всего осуществить после объявления имени родительского пакета. Схема класса полученной модели приведена на рисунке 2.
Рисунок 2 – Схема класса
модели адресов
Теперь, когда процесс описания содержимого модели рассмотрен, следует привести полученный в результате код модели сущности адресов, он приведён в приложении А.1. Исходный код остальных моделей будет составлен поэтому же шаблону и потому рассмотрен не будет.
Далее следует выполнить построение контроллера фасада модели, отвечающего за взаимодействие с моделью.
3.3.2 Создание контроллеров фасада моделей
Этот блок должен предоставлять пользователям возможности просмотра, редактирования и создания записей, а также поиска по таблице и механизм постраничной навигации для случая большой выборки. Контроллер фасада модели должен реализовывать функционал, описанный выше. Все контроллеры фасадов будут храниться в пакете ViewSession. Для начала следует объявить поле для хранения модели, с которой будет вестись работа.
Для реализации возможности поиска по таблице в контроллер фасада модели следует добавить метод посылающий запрос к базе данных, для этого можно использовать как встроенный в JPA – JPQL, так и воспользоваться методом построения запросов на основе критериев. Использование JPQL предполагает написание SQL кода в соответствующем синтаксисе. Использование же второго способа не требует ничего кроме Java кода, однако конструкции такого кода могут получаться весьма громоздкими, однако к преимуществам данного метода можно отнести возможность абстракции от конкретного объекта. При этом оба метода дают одинаковый результат. Для работы с базой данных в дальнейшем будет использоваться JPQL, в связи с отсутствием сложных запросов и общей компактностью, и простотой записи. Таким образом для возможности поиска следует просто добавить в контроллер фасада модели соответствующий метод задать в качестве возвращаемого значения список объектов типа целевого класса и написать соответствующий запрос к базе данных. Так код содержащий запрос выполняющий поиск по полю идентификатора адреса, будет выглядеть следующим образом: