ПСУБД ЛР №3 (4 часа)
.pdfМинистерство образования Республики Беларусь Учреждение образования «Полоцкий государственный университет»
Факультет информационных технологий Кафедра технологий программирования
Методические указания
к выполнению лабораторной работы №3
по дисциплине «Постреляционные СУБД»
для специальности 1-40 01 01 Программное обеспечение информационных технологий
на тему «Сложные свойства. Генерация тестовых данных»
Новополоцк, 2017 г.
Тема: Сложные свойства. Генерация тестовых данных.
Цель работы: Изучить понятие сложных свойств. Научиться генерировать тестовые данные в СУБД «Cachè».
Теоретическая часть
Потоки
Потоком данных называют большое неструктурированное множество данных, которое нужно хранить в базе данных. Caché SQL обеспечивает хранение данных типа BLOBs (Binary Large Objects) и CLOBs (Character Large Objects) в базе данных. BLOBs используются для хранения двоичных данных, таких как рисунки, изображения, в то время как CLOBs используются для хранения символьной информации. Например, потоки данных могут применяться для хранения документов, технических чертежей или рисунков. Поскольку они могут быть очень велики, Caché не оперирует с потоками данных как с атомарной информацией, а предоставляет прикладным программам методы блочной записи и считывания данных. В соответствии с содержимым различают потоки данных типа CHARACTERSTREAM (состоящие из символов) BINARYSTREAM (состоящие из двоичных данных). Для манипулирования потоками используются методы класса %STREAM, в листинге 1 приведем пример использования данного класса.
Листинг 1 – Пример использования %STREAM
Class MyApp.JournalEntry Extends %Persistent [ClassType = persistent]
{
Property ItemDate As %Date;
Property PictureOfTheDay As %Stream [ Collection = binarystream ]; Property EventsOfTheDay As %Stream [ Collection = characterstream ];
}
Класс MyApp.JournalEntry имеет два свойства типа потока: PictureOfTheDay – двоичный поток, EventsOfTheDay – символьный поток.
В зависимости от того, как определено соответствующее свойство, потоки данных автоматически сохраняются в базе данных Caché либо в файлах операционной системы. Это различие достигается путем присвоения параметру STORAGE значения GLOBAL, либо FILE. Следующий параметр LOCATION применяется, когда требуется задать имя глобала либо имя каталога файловой системы, в котором должен храниться поток данных. При этом поток данных всегда представляет собой поток данных, а не какой-либо самостоятельный объект. Примеры использования параметров STORAGE и LOCATION продемонстрированы в листинге 2.
Листинг 2 – Пример использования Storage/Location
Property GMemo As %Stream (STORAGE="GLOBAL", LOCATION="^MyStream") [collection = binarystream];
Property FMemo As %Stream (STORAGE="FILE", LOCATION="C:\Stream") [collection = binarystream];
В примере значения свойства GMemo будут сохранены в глобале ^MyStream, в то время как значения свойства FMemo будут сохраняться в файле с автоматически генерируемым именем в директории C:\Stream.
По умолчанию потоки типа GLOBAL сохраняются в глобале ^PackageClassS. Файловые потоки по умолчанию сохраняются в текущей директории.
Свойства коллекции
Свойство коллекция состоит из набора элементов одного типа. Caché поддерживает два типа коллекций: списки (List) и массивы (Array). Коллекция список состоит из упорядоченного набора элементов, т.е. каждому элементу ставится в соответствие его порядковый номер. Коллекция массив состоит из набора пар вида: <ключ> <значение>, упорядоченных по ключу. В таблице 1 представлен пример массива прививок.
Таблица 1 – Пример массива
Ключ |
Значение |
2.04.1999 |
От гриппа |
10.05.2001 |
От клещевого энцефалита |
20.11.2002 |
От дифтерии |
Коллекции могут содержать константы, встроенные объекты и ссылки на объекты. Например, следующий код задает свойство Colors, как коллекцию список типа %String:
Property Colors As %String [collection = list];
Аналогично, Caché поддерживает коллекции объектов, как, например, в следующем примере свойство Doctors является коллекцией ссылок типа массив на объекты Doctor:
Property Doctors As Doctor [collection = array];
Генерация тестовых данных
Caché поддерживает множественное наследование. Это, например, позволяет использовать утилиту, которая автоматически создает и сохраняет указанное количество объектов в БД и заполняет их свойства псевдослучайными данными. Для того, чтобы воспользоваться данной утилитой, необходимо унаследовать класс от системного класса %Populate.
Отредактируем класс Reader, добавив в список наследования класс
%Populate:
Class Test.Reader Extends (Test.Human, %Populate)
Откомпилируем класс. Для создания 10 новых объектов в Терминале следует прописать:
USER>do ##class(Test.Reader).Populate()
Чтобы создать другое количество объектов, укажем необходимое число в скобках:
USER>set"cnt"="##class(Test.Reader).
Populate(15) USER>write cnt
15
Метод Populate возвращает число фактически созданных объектов. Кроме того, он автоматически заполняет не только литеральные свойства, но и ссылочные, в том случае, если объекты необходимого класса существуют.
Populate(count As %Integer = 10, verbose As %Integer = 0, DeferIndices As Integer = 1, ByRef objects As %Integer =0) returns %Integer
создаёт count объектов класса и сохраняет их в БД;
если verbose – истина, то детали отражаются в консоле;
если DeferIndices – истина, то индексы сортируются в конце
операции;
возвращает количество успешно созданных экземпляров.
Метод PopulateSerial() returns %String создаёт единственный экземпляр встраиваемого класса.
Абстрактный метод OnPopular() returns %Status.
Для заполнения тестовыми данными созданных классов в Caché предусмотрен специальный метод Populate().
POPSPEC = "Company()" – сообщает генератору тестовых данных, чего от него хотят, а то он сам придумывает, что выдавать. Пример использования отображен в Листинг 8.
Метод OnPopulate() применяется, если необходимо лучше контролировать генерацию данных. При активации Populate(), происходит моментальный переброс на метод OnPopulate.
Листинг 3 – Пример структуры метода OnPopulate()
Method OnPopulate() As %Status
{
// body of method here...
}
Листинг 4 - Пример использования метода OnPopulate()
Method OnPopulate() As %Status
{
Do ..Memo.Write("Default value") QUIT $$$OK
}
Примеры:
Листинг 5 – Некоторые свойства класса «Person»
/// фотография
Property Photo As %Stream(LOCATION = "C:\BD", STORAGE = "FILE") [ Collection = binarystream ];
/// биография
Property Biography As %Stream(LOCATION = "^BiographyMen", STORAGE = "GLOBAL") [ Collection = characterstream ];
/// друзья
#Property Friends As Person [ Collection = list ];
Листинг 6 – Пример отношения один ко многим
Class User.Company Extends %Persistent [ ClassType = persistent]
{
Relationship Clients As User.Client [ Cardinality = many, Inverse = MyCompany ];
Property OfficeNumber as %Integer;
}
Class User.Client Extends %Persistent [ ClassType = persistent]
{
Relationship MyCompany As User.Company [ Cardinality = one, Inverse = Clients ];
Property Name as %String;
}
Листинг 7 – Пример отношения родитель ребенок
Class User.Book Extends %Persistent [ClassType = persistent]
{
Relationship Chapters As User.Chapter [Cardinality = children, Inverse = Book];
}
Class User.Chapter Extends %Persistent [ClassType = persistent]
{
Relationship Book As User.Book [Cardinality = parent, Inverse = Chapters];
}
Листинг 8 – Хранимый класс Person
Class User.Person Extends (%Persistent, %Populate) [ ClassType = persistent, ProcedureBlock ]
{
/// Имя
Property Name As %Name;
/// Список имен детей
Property Kids As %String [ Collection = list ];
///Для свойства Kids задаем стандартный метод генерации данных
///Name() из класса %Library.PopulateUtils и задаем максимальное
///количество элементов в списке - 7. Parameter POPSPEC = "Kids:Name():7";
///Домашний адрес
Property HomeAddr As Address (POPSPEC=".HomeAddr.PopulateSerial()");
}
Чтобы создать хранимый класс выполняем действия как на рисунках. Жмём на классы правой кнопкой и выбираем «Создать класс».
Далее вводим название класса и жмём далее.
Выбираем Persistent(может храниться в базе данных) и жмём далее.
Выбираем checkbox Генерация тестовых данных и жмём готово.
В итоге получим новый класс, изображенный на рисунке ниже.
Встраиваемый класс создаётся также как и хранимый только вместо Persistent выбираем Serial (может быть встроен в объекты Persistent).
Листинг 9 – Встраиваемый класс Address
Class User.Address Extends (%SerialObject, %Populate) [ ClassType = serial, ProcedureBlock ]
{
Property City As %String;
Property Street As %String; Property HomeNumber As %Integer;
///Для генерации значений свойства City
///используется стандартный метод генерации значений City()
///Для генерации значений свойства Street используется
///пользовательский метод генерации значений MyStreet из класса
MyClass.
Parameter POPSPEC = "City:City(),Street:##Class(MyClass).MyStreet()";
}
Листинг 10 – Метод MyClass для генерации данных
Class User.MyClass
{
ClassMethod MyStreet() As %String
{
n t1,t2
s t1=$lb("Чкалова","Фрунзе","Кирова","Людникова") s t2=$lb("улица","проспект","переулок")
Quit $li(t2,$r($ll(t2))+1)_" "_$li(t1,$r($ll(t1))+1)
}
}
Листинг 11 – Вызов метода генерации данных
User>do ##class(User.Person).Populate(10,1)
Практическая часть
Содержание задания:
Для созданных классов из предыдущей лабораторной работы:
1 Проанализируйте свойства классов сущностей, созданных ранее. Определите для каких классов необходимо определить сложные свойства:
а) потоки (бинарный или символьный); б) коллекции (списки, массивы);
в) отношения (один ко многим, родитель-ребенок). Например, поле «Cover» (обложка) в классе «Book» или «Photo» в классе
«Person» можно определить, как поле бинарного потока, а «Biography» – как поле символьного потока.
2 Настройте способ и место хранения потоков используйте пару параметров STORAGE и LOCATION.
3 Разработайте методы для генерации тестовых данных вашего приложения минимум для двух хранимых классов и одного встроенного, используя возможности класса %Library.Populate.
4 Сгенерируйте не менее 50 объектов с осмысленными, корректными данными, соответствующими вашей предметной области.
5 Для генерации «настройте» параметр POPSPEC для свойства и для
класса.
6 В случае необходимости проверяйте корректность сгенерированных данных или генерируйте тестовые данные для закрытых свойств в методе
OnPopulate().
7 Вызов методов генерации данных проводите в Терминале
Продемонстрируйте работу преподавателю!