Скачиваний:
103
Добавлен:
02.05.2014
Размер:
2.54 Mб
Скачать

24.4. Простой пример

В предыдущей главе были представлены базовые концепции объектного подхода. В данной главе на простом примере последовательно демонстрируется применение этих идей на практике, а именно — как определяется объектная база данных, как она попол­няется данными, как в ней выполняются операции извлечения и обновления данных. В рассматриваемом примере используются объектная СУБД GemStone (разработка корпо­рации GemStone Systems) и ее язык запросов OPAL [24.14]. Язык OPAL, в свою очередь, основывается на языке Smalltalk [24.26], одном из наиболее истинно объектных языков (поэтому он здесь и используется).

Замечание Необходимо добавить, что язык Smalltalk появился на рынке раньше, чем язык С++, и гораздо раньше, чем язык Java. Однако несмотря на это два последних языка являются менее "чистыми" объектными языками, чем Smalltalk.

В качестве примера воспользуемся упрощенной версией базы данных профессио­нальной подготовки из упр. 8.10 главы 8. В этой базе данных содержится информация о схеме подготовки и обучения специалистов внутри некоторой компании. Для каждого курса обучения (COURSE) в базе данных содержится описание отдельных потоков, органи­зованных для его изучения (OFFERING). Для каждого потока хранятся данные обо всех его слушателях (ENROLLMENT) и преподавателях (TEACHER). Кроме того, в базе содержатся сведения о сотрудниках компании. Реляционную версию базы данных можно описать сле­дующим образом.

COURSE

OFFERING

TEACHER

ENROLLMENT EMP

COURSE!, TITLE }

COURSE!, OFF!, OFFDATE, LOCATION } COURSE!, OFF!, EMP! } COURSE!, OFF*, EMP!, GRADE } EMP!, ENAME, SALARY, POSITION }

На рис. 24.6 показана диаграмма связей для рассматриваемой базы данных. Более подробно она описана в главе 8, в упражнениях и ответах к упражнениям.

COURSE

OFFERING

ENROLLMENT

TEACHER

EMPLOYEE

Рис. 24.6. Диаграмма связей для образовательной базы данных

Определение данных

Теперь перейдем к определению данных на языке OPAL для образовательной базы данных. Ниже приводится первое определение объектного класса ЕМР, описывающего сотрудников (для удобства строки этого определения пронумерованы).

1 OBJECT SUBCLASS : 'ЕМР'

  1. INSTVARNAMES : f[ 'EMPf', 'ENAME', 'POSITION' ]

  2. CONSTRAINTS : f[ f[ IEMPf, STRING ] ,

  1. [ iENAME, STRING ],

  2. [ IPOSITION, STRING ] ] .

Пояснения. В строке 1 определен объектный класс ЕМР, производный от встроенно­го класса OBJECT. (Согласно терминологии языка OPAL в строке 1 отсылается сооб­щение объекту OBJECT с запросом выполнить метод SUBCLASS, причем с помощью предложений INSTVARNAMES и CONSTRAINTS указываются параметры вызова этого ме­тода. Для определения нового класса (как и всего прочего) необходимо отослать со­общение объекту.) В строке 2 указывается, что объекты класса ЕМР имеют три закры­тые переменные экземпляра— EMPf, ENAME и POSITION, а в строках 3-5 на эти пере­менные экземпляра накладываются ограничения, указывающие, что они должны со­держать объекты класса STRING.

Замечание. В настоящей главе опускаются чисто синтаксические подробности, несу­щественные для преследуемых нами целей (например, вездесущие знаки присутст­вующие в приведенном выше примере).

Подчеркнем, что переменные экземпляра EMPf, ENAME и POSITION — закрытые пере­менные для класса ЕМР, поэтому доступ к ним по именам допустим только в методах это­го класса. В качестве примера ниже даны определения методов "получить и установить", т.е. методов, позволяющих выбрать и обновить номера служащих (здесь символ "А" можно читать как "возвратить").

METHOD : ЕМР GET EMPf ~ЕМР#

I

METHOD : EMP

SET EMPi : EMPi PARM ~EMP| := EMP? PARM

%

В следующем подразделе о методах определения мы поговорим подробнее. А сейчас рассмотрим определение класса описания курса COURSE.

OBJECT SUBCLASS INSTVARNAMES CONSTRAINTS

'COURSE'

t[ 'COURSE!', 'TITLE', #[ #[ !C0URSE!, STRING [ !TITLE, STRING ] [ iOFFERINGS, OSET

'OFFERINGS' ]

Пояснения. В строке 5 определена переменная OFFERINGS, которая содержит объект класса 0SET, или, точнее, идентификатор объекта класса 0SET. Выражаясь неформально, переменная OFFERINGS обозначает множество всех потоков для данного курса. Иначе го­воря, связь "курс — поток" моделируется с помощью иерархии вложения, в которой по­токи концептуально содержатся внутри соответствующего курса. Определение класса 0SET будет дано ниже, а определение класса потока OFFERING может быть записано так.

OBJECT SUBCLASS INSTVARNAMES

'OFFERING' ![ 'OFF!'

CONSTRAINTS

'ODATE', 'LOCATION', 'ENROLLMENTS', 'TEACHERS' ] ![ !0FF!, STRING ] , [ !0DATE, DATETIME ], [ LOCATION, STRING ], [ !ENROLLMENTS, NSET ], 8 [ !TEACHERS, TSET ] ] .

1 OBJECT SUBCLASS

  1. INSTVARNAMES

  2. CONSTRAINTS 4

Пояснения. В строке 7 определяется закрытая переменная экземпляра ENROLLMENTS, содержащая идентификатор объекта класса NSET. Говоря неформально, переменная ENROLLMENTS описывает множество всех слушателей в данном потоке. Аналогично пере­менная TEACHERS описывает множество всех преподавателей потока. Следовательно, здесь вновь используется представление иерархии вложения. Определения классов NSET и TSET будут даны ниже. Определение класса слушателей ENROLLMENT может быть запи­сано следующим образом.

'ENROLLMENT' ![ 'ЕМР', 'GRADE' ] ♦[ |[ «ЕМР, ЕМР ] ,

[ IGRADE, STRING ] ].

Пояснения. В строке 3 определяется закрытая переменная экземпляра ЕМР, содержа­щая идентификатор объекта класса ЕМР, представляющий отдельного сотрудника, который является слушателем курса.

Замечание. Чтобы продолжить иерархию вложения, объект ЕМР помещается в объект ENROLLMENT. Однако здесь можно заметить асимметрию: зачисление сотрудника на обу­чение в разные потоки описывается как отношение типа "многие ко многим", однако члены этого отношения, сотрудники и потоки, обрабатываются совершенно по-разному.

И наконец рассмотрим объекты, представляющие преподавателей. В нашем примере следует несколько отвлечься от исходной реляционной версии базы данных и рассмот­реть преподавателей (TEACHER) как подкласс класса сотрудников (ЕМР).

1 ЕМР SUBCLASS : 'TEACHER'

  1. INSTVARNAMES : f[ 'COURSES' ]

  2. CONSTRAINTS : f[ §[ ICOURSES, CSET ] ] .

Пояснения. В строке 1 определен объектный класс TEACHER, который является подклассом ранее определенного класса ЕМР (иначе говоря, TEACHER "ISA" ЕМР). Таким образом, каждый от­дельный объект TEACHER имеет закрытые переменные экземпляра EMPf, ENAME и POSITION (которые унаследованы от класса ЕМР8), а также переменную COURSES, которая содержит иден­тификатор объекта класса CSET. Объект CSET определяет множество всех курсов, которые ведет конкретный преподаватель. Каждый объект TEACHER также наследует все методы класса ЕМР.

Как уже отмечалось, в предыдущих определениях классов предполагалось существо­вание нескольких классов коллекций (например, коллекций объектов потоков, учеников, преподавателей и т.д.), но они не были определены. Теперь следует дать точное опреде­ление коллекции каждого класса, а именно: ESET, CSET, OSET, NSET и TSET. Например, объект класса CSET будет состоять из множества идентификаторов отдельных объектов класса COURSE. Ниже даются определения всех этих классов, начиная с класса ESET.

1 SET SUBCLASS : 'ESET'

2 CONSTRAINTS : EMP .

Пояснения. В строке 1 дается определение класса ESET, который является подклассом встроенного класса SET. В строке 2 на объекты класса ESET накладывается ограничение: они должны быть множествами идентификаторов объектов класса ЕМР. В общем случае может существовать произвольное число объектов класса ESET, но в данной ситуации будет создан только один объект (подробности приводятся в следующем подразделе), который будет содержать множество идентификаторов всех объектов класса ЕМР. Выражаясь не­формально, объект ESET можно считать аналогом базовой переменной-отношения ЕМР в ре­ляционной версии базы данных.

Определения классов CSET, OSET, NSET и TSET аналогичны (они приводятся ниже). Од­нако для каждого из них придется создать не один, а несколько объектов соответствую­щей коллекции классов. Например, в нашем случае будет существовать столько коллек­ций объектов OSET, сколько существует отдельных объектов COURSE.

SET SUBCLASS : 'CSET' CONSTRAINTS : COURSE .

SET SUBCLASS : 'OSET'

CONSTRAINTS : OFFERING .

SET SUBCLASS : 'NSET'

CONSTRAINTS : ENROLLMENT .

Заметим, что здесь наследуется закрытое представление (т.е. физическая реализация).


SET SUBCLASS : 'TSET' CONSTRAINTS : TEACHER .

Заполнение базы данных

Теперь обсудим, как можно поместить в рассматриваемую базу данных требуемую информацию. При этом остановимся на пяти основных типах объектов (сотрудники, кур­сы, потоки, слушатели, преподаватели). Начнем с сотрудников. Напомним о нашем на­мерении собрать вместе идентификаторы всех объектов ЕМР в единственном объекте ESET. Таким образом, прежде всего необходимо создать объект ESET.

0ID_0F_SET_0F_ALL_EMPS := ESET NEW .

Правая часть этого выражения возвращает объектный идентификатор (OID) нового пустого экземпляра объекта класса ESET (т.е. пустое множество идентификаторов объек­тов класса ЕМР), а затем идентификатор этого нового экземпляра присваивается про­граммной переменной 0ID_0F_SET OF_ALL_EMPS. Говоря неформально, эта переменная обозначает множество всех сотрудников.

Теперь всякий раз при создании нового объекта класса ЕМР идентификатор этого объ­екта следует помещать в объект ESET, идентификатор которого хранится в переменной 0ID_0F_SET_0F_ALL_EMPS. Для создания объекта класса ЕМР и вставки его идентификато­ра в объект класса ESET необходимо определить метод или же написать программу, ко­торая выполнит эту задачу.

1 METHOD : ESET " анонимный! "

  1. ADD EMPI : EMPI PARM " параметры "

  2. ADD~ENAME : ENAME PARM

  3. ADD~P0S : P0S_PARM

  4. j EMP_0ID I " локальная переменная "

  5. EMP OID := EMP NEW . " новый сотрудник "

  6. EMP~0ID SET EMPI : EMPi PARM ; " инициализация "

8 ~ SET~ENAME : ENAME PARM ;

9 SET~P0S : POS PARM .

10 SELF ADD: EMP OID . ~ " вставка "

11 %

Пояснения

  • В строке 1 начинается запись кода данного метода (который завершается симво­лом "%" в строке 11) для объектов класса ESET. (На самом деле в системе во время выполнения программы будет существовать всего один объект этого класса.)

  • В строках 2-4 определены три параметра с внешними именами ADD_EMPI, ADD_ENAME и ADD_P0S. Эти имена будут использованы в сообщениях, вызывающих данный метод. Соответствующие внутренние имена EMPf_PARM, ENAME_PARM и P0S_PARM будут использоваться только внутри кода реализации данного метода.

  • В строке 5 определена локальная переменная EMP_0ID, а в строке 6 ей присвоен идентификатор нового неинициализированного экземпляра объекта класса ЕМР.

  • В строках 7-9 посылается сообщение новому объекту класса ЕМР с указанием трех методов (SET_EMP#, SETJENAME и SET_P0S) и передачей одного аргумента каждому из них (EMPI PARM для SET~EMP|, ENAME PARM для SET ENAME и POS PARM для SET POS).

Замечание. Здесь предполагается, что SET_EMPl является методом, который ис­пользуется для объекта класса ЕМР и предназначается для присвоения некоторого значения переменной EMPf. Аналогично определяются методы SETJ2NAME и SET_P0S. Несколько подробнее эти методы рассматриваются ниже.

■ В строке 10 посылается сообщение объекту SELF. Это имя объекта является спе­циальным обозначением, представляющим во время выполнения тот самый теку­щий объект, в котором определен указанный метод (т.е. сообщение посылается самому текущему целевому объекту). Сообщение вызывает встроенный метод ADD (этот метод содержится в каждом классе, определяющем "коллекцию"). В резуль­тате идентификатор объекта, который содержится в локальной переменной EMP_0ID, будет вставлен в объект, идентифицируемый значением переменной SELF (в данном случае это будет объект ESET, содержащий идентификаторы всех суще­ствующих на текущий момент объектов класса ЕМР).

Замечание. Переменная SELF необходима потому, что параметр, соответствующий объекту-получателю, не имеет собственного имени (см. строку 1).

■ Обратите внимание, что, как отмечено в комментарии к строке 1, определенный здесь метод остается анонимным. В общем случае в языке OPAL методы не имеют имен; вместо этого для них используется сигнатура (т.е. комбинация имени класса, в котором он применяется, и внешних имен их параметров). Однако при этом возни­кает опасность создания неуклюжих и огромных выражений. Можно отметить и еще один недостаток: если два метода одного и того же класса используют одни и те же параметры, то для этих методов должны использоваться разные внешние параметры.

Теперь новый метод, созданный для вставки в базу данных новых объектов класса ЕМР, можно применить следующим образом.

OID OF SET OF ALL EMPS ADD EMPf : 'E009'

ADD~ENAME : 'Helms' ADD_P0S : 'Janitor' .

При использовании приведенного выражения будет создан объект класса ЕМР для со­трудника с номером 'Е009', а идентификатор этого объекта будет добавлен к множеству всех идентификаторов объектов класса ЕМР.

Обратите внимание, что встроенный метод NEW никогда не должен использоваться для класса ЕМР, кроме тех случаев, когда он является частью только что определенного метода. Иначе могут быть созданы лишние объекты класса ЕМР, которые не будут пред­ставлены в "множестве всех сотрудников".

Замечание. Следует принести извинения за слишком частое повторение таких выра­жений, как "множество всех сотрудников" и "только что определенный метод", однако сложно описывать то, что не имеет собственного имени.

А теперь займемся курсами. Объекты для сотрудников представляют собой наиболее простой случай, поскольку они соответствуют "регулярным объектам" (согласно терми­нологии модели типа "сущность/связь") и не содержат никаких других объектов (не счи­тая неизменяемых). Далее следует рассмотреть более сложный случай объектов для кур­сов, которые (несмотря на то, что они все еще остаются "регулярными объектами") кон­цептуально содержат другие изменяемые объекты. В целом, чтобы создать объекты для курсов, необходимо выполнить следующие действия.

  1. Применить метод NEW для класса CSET с целью создания исходно пустого "множества всех курсов" (на самом деле — множества идентификаторов объектов класса COURSE).

  2. Определить метод для создания нового объекта класса COURSE и вставки его иден­тификатора в "множество всех курсов". При создании этого объекта потребуется задать некоторые значения для параметров COURSE! и TITLE. Кроме того, с помо­щью метода NEW класса 0SET потребуется также создать исходно пустое множество потоков (на самом деле — идентификаторов объектов класса OFFERING), а затем разместить идентификатор этого пустого множества потоков в переменной 0FERINGS внутри нового объекта класса COURSE.

  1. Вызвать только что определенный метод для каждого отдельного курса.

Теперь создадим объекты потоков. Для этого необходимо выполнить следующие действия.

1. Определить метод для создания нового объекта класса OFFERING. Этот метод должен принимать в качестве параметров значения переменных OFFt, 0DATE и LOCATION и приводить к созданию нового объекта класса OFFERING с указанными параметрами. Кроме того, потребуется выполнить некоторые дополнительные действия.

» Для создания исходно пустого множества слушателей (идентификаторов объек­тов класса ENROLLMENT) следует применить метод NEW для класса NSET, а затем разместить идентификатор этого пустого множества слушателей в переменной ENROLLMENTS внутри нового объекта класса OFFERING.

■ Для создания исходно пустого множества преподавателей (идентификаторов объ­ектов класса TEACHER) следует применить метод NEW для класса NSET, а затем раз­местить идентификатор этого пустого множества преподавателей в переменной TEACHERS внутри нового объекта класса OFFERING.

2. Данный метод принимает в качестве параметра значение переменной COURSE! и применяет его следующим образом.

■ Используя указанное значение параметра, необходимо найти объект класса COURSE, соответствующий новому объекту класса OFFERING. Как это можно вы­полнить, описано в следующем подразделе.

Замечание. Безусловно, такой метод не позволит создать объект для нового по­тока, если не будет найден соответствующий ему курс обучения. Далее в этой главе такие исключительные случаи рассматриваться не будут.

  • Следует найти "множество всех потоков" для данного объекта класса COURSE.

  • Добавить идентификатор нового объекта класса OFFERING к соответствующему "множеству всех потоков".

Заметьте, что (как уже упоминалось в этой главе) здесь нельзя избежать примене­ния таких пользовательских ключей, как COURSE!. Действительно, они необходимы не только для отображения объектов окружающего мира, но и для организации подстановок справочных данных внутри базы данных.

3. Наконец следует вызвать только что определенный метод для каждого отдель- ного потока.

Обратите внимание, что (в соответствии с используемым представлением иерархии вложения) здесь не было создано "множество всех потоков". В результате для выполне­ния запроса, в котором данные коллекции используются в качестве анализируемой об­ласти (например, для запроса "Найти все потоки, преподаваемые в Нью-Йорке"), потре­буется дополнительно создать некоторую процедуру (см. следующий подраздел).

Теперь рассмотрим процедуру создания объектов слушателей. Эти объекты (ENROLLMENT) отличаются от объектов потоков тем, что содержат переменную экземпля­ра ЕМР, значение которой является идентификатором соответствующего объекта ЕМР. По­этому последовательность действий должна быть такой.

1. Определить метод для создания нового объекта класса ENROLLMENT. В этом методе в качестве аргументов используются значения переменных COURSEI, OFFf, EMPI и GRADE и создается новый объект ENROLLMENT с заданным значением аргумента GRADE. Кроме того, требуется выполнить некоторые дополнительные действия.

  • Использовать значения COURSE! и OFFf для нахождения объекта OFFERING, соот­ветствующего новому объекту класса ENROLLMENT.

  • Найти "множество всех слушателей" для данного объекта класса OFFERING.

  • Добавить идентификатор нового объекта класса ENROLLMENT к соответствующему "множеству всех слушателей".

Кроме того, потребуется следующее.

  • Использовать значение переменной EMPf для нахождения соответствующего объекта ЕМР.

  • Разместить идентификатор объекта ЕМР в переменной ЕМР внутри нового объекта класса ENROLLMENT.

2. Вызывать только что определенный метод для каждого отдельного потока.

И наконец перейдем к созданию объектов преподавателей. Различие между способа­ми создания объектов для преподавателей и потоков заключается в том, что класс TEACHER является подклассом класса ЕМР. Ниже приведена последовательность действий, которые необходимо выполнить в данном случае.

1. Определить метод создания нового объекта класса TEACHER. Этот метод принимает в качестве аргументов значения переменных COURSE!, OFFf и EMPf. Потребуются также некоторые дополнительные действия.

  • Использовать значение переменной EMPf для нахождения соответствующего объекта класса ЕМР.

  • Преобразовать объект класса ЕМР в объект класса TEACHER (поскольку этот со­трудник теперь является также преподавателем). Специфика подобного преобра­зования зависит от конкретной системы (см. главу 19), и здесь этот вопрос рас­сматриваться не будет.

  • Использовать значения переменных COURSEf и OFFf для поиска объекта класса OFFERING, соответствующего новому объекту класса TEACHER.

  • Найти "множество всех преподавателей" для этого объекта OFFERING.

■ Добавить идентификатор нового объекта класса teacher к соответствующему "множеству всех преподавателей".

  1. Определить множество всех курсов, которые может вести данный преподаватель, а также задать соответствующим образом значение переменной courses в новом объекте класса teacher. Однако здесь эти подробности будут опущены.

  2. Вызывать только что определенный метод для каждого объекта, описывающего отдельного преподавателя.

Операции извлечения

Прежде чем приступить к подробному описанию операций извлечения, следует отме­тить, что (хотя это и вполне очевидно) язык OPAL, как и другие объектные языки в це­лом, функционирует по принципу последовательной обработки отдельных записей, а не их множеств. Следовательно, для решения большинства проблем программист должен создать некоторую процедуру.

Рассмотрим в качестве примера запрос "Найти все потоки для курса с номером 'с001', которые преподаются в городе 'New York'". Для простоты предположим, что есть переменная 00s0ac, значение которой является идентификатором "набора всех кур­сов". Ниже приводится код для такого запроса.

Соседние файлы в папке Дейт К. Дж. Введение в системы баз данных [7 издание]