Постреляционная СУБД
Caché Учебный курc
Сиротюк Олег
InterSystems Corporation, 2002
Цель занятий. Целью занятий является изучение основных принципов объектноориентированного проектирования и разработки информационных систем на базе постреляционной объектно-ориентированной базы данных Caché. Объем занятий ограничивается материалом, необходимым для реализации курсовых, дипломных проектов студентами старших курсов высших учебных заведений технического профиля. Требования к знаниям и умениям по окончанию курса. После окончания курса студенты должны владеть следующими навыками: • Освоить основные принципы объектно-ориентированной методологии разработки информационных систем и баз данных. • Уметь разрабатывать проекты на базе основных UML диаграмм. • Разрабатывать объектную модель Caché. Различать основные типы классов, а также типы основных элементов классов. • Уметь разрабатывать программы на COS. Уметь работать со свойствами и методами класса и экземпляра, а также уметь манипулировать данными в БД. • Уметь создавать приложения CSP, обеспечивающие манипулирование данными из БД Caché. • Уметь создавать встроенные запросы SQL. • Получить навыки администрирования БД Caché.
2
Содержание курса. 1. Основные концепции объектно-ориентированной методологии. Класс и объект. Полиморфизм, инкапсуляция и наследование. Способы представления объектных моделей (UML). 2. Несколько фактов об разработчике Caché InterSystems corporation. 3. Объектная модель Caché. 4. Caché Object. В главе дается описание классов Caché и основных элементов класса. Приводятся примеры создания классов и элементов с помощью инструментальных средств СУБД Caché 5. Изучение Caché Object Script на примерах написания кода методов и работы с объектами. Методы – как основные элементы реализации требуемых функций информационных систем. Изучение Caché Terminal, Explorer. Создание, редактирование, удаление объектов. Использование класса %ResultSet для создания динамических SQL-запросов. 6. CSP. Архитектура CSP, использование предопределенных тегов, разработка собственных тегов. 7. Администрирование Caché. Изучение Configuration Manager. Экспорт/Импорт данных из/в Caché. Рекомендуемая литература. 1. Документация, поставляемая с Caché. 2. СУБД Caché Объектно-ориентированная разработка приложений. Учебный курс. В.Кирстен и др. СПб: Питер, 2001г. 3. Постреляционная технология Caché для реализации объектных приложений. Н.Е. Кречетов и др. М: МИФИ, 2001г. 4. Материалы сайта www.intersystems.ru . С вопросами можно обращаться по адресу:
[email protected].
3
Основные концепции объектно-ориентированной методологии. Фундаментальным понятием объектно-ориентированного программирования является понятие класса и объекта. При этом под классом понимают некоторую абстракцию совокупности объектов, которые имеют общий набор свойств и обладают одинаковым поведением. Каждый объект в этом случае рассматривается как экземпляр соответствующего класса. Важной особенностью классов является возможность их организации в виде некоторой иерархической структуры. При этом в качестве наиболее общего понятия или категории берется понятие, имеющее наибольший объем и, соответственно, наименьшее содержание. Это самый высокий уровень абстракции для данной иерархии. Затем данное понятие постепенно некоторым образом конкретизируется до тех пор, пока на самом нижнем уровне не будет получено понятие, дальнейшая конкретизация которого в данном контексте либо невозможна, либо нецелесообразна. Основными принципами ООП являются наследование, инкапсуляция и полиморфизм. Наследование – это принцип, в соответствии с которым знание о наиболее общей категории разрешается применять для более узкой категории. При этом, если некоторый более общий или родительский класс (предок) обладает фиксированным набором свойств и определенным поведением, то производный от него класс (потомок) должен иметь этот же набор свойств и такое же поведение, а также дополнительные свойства и поведение, которые будут характеризовать уникальность полученного таким образом класса. Инкапсуляция – термин, характеризующий сокрытие отдельных деталей внутреннего устройства классов от внешних по отношению к нему объектов или пользователей. Разделяют интерфейсную часть класса и конкретную реализацию. Интерфейсная часть необходима для взаимодействия с любыми другими объектами. Реализация же скрывает особенности реализации класса, т.е. все, что не относиться к интерфейсной части. Полиморфизм – это принцип, в соответствии с которым действия, выполняемые одноименными методами, могут отличаться в зависимости от того, какому из классов относиться тот или иной метод. Язык UML представляет собой общецелевой язык визуального моделирования, который разработан для спецификации, визуализации, проектирования и документирования компонентов программного обеспечения, бизнес-процессов и других систем. В рамках UML все представления о модели сложной системы фиксируются в виде специальных графических конструкций, получивших название диаграмм: 1. Диаграмма вариантов использования. Описывает функциональное назначение системы. 2. Диаграмма классов. Служит для представления статической структуры модели системы в терминологии объектно-ориентированного программирования. 3. Диаграмма состояний. Служит для описания возможных последовательностей состояний и переходов, которые в совокупности характеризуют поведение элемента модели в течение его жизненного цикла. 4. Диаграмма деятельности. Позволяет реализовать особенности процедурного и синхронного управления, обусловленного завершением внутренних деятельностей и действий 5. Диаграмма последовательности.
4
6. Диаграмма кооперации. 7. Диаграмма компонентов. 8. Диаграмма развертывания. Краткая информация о разработчике постреляционной СУБД Caché InterSystems Сorporation "Мы ведем разработчиков к успеху!" - так звучит девиз, который в 1978 году выбрал для своей компании InterSystems Corporation выпускник Массачусетского Технологического Института и основатель фирмы Терри Рэйгон. Под этим девизом работают сейчас свыше 360 сотрудников, помогая своим клиентам - профессиональным разработчикам - становиться самыми успешными в мире. Как и прежде, секрет успеха лучших программных решений кроется в том, чтобы оптимально отражать сложные требования реального мира. А так как требования реального мира почти каждый день меняются, то прикладные решения на базе нашей постреляционной СУБД Caché пользуются исключительным успехом. И не только у разработчиков программного обеспечения, но и, прежде всего, у пользователей, чей успех более чем когдалибо зависит от своевременного доступа к информации круглый год, семь дней в неделю, 24 часа в сутки. Корпорация InterSystems, штаб-квартира которой находится в городе Кембридж, штат Массачусетс, США, является ведущим поставщиком высокопроизводительных систем управления базами данных, оптимизированных для Web, и приложений в архитектуре клиент-сервер, ориентированных на интенсивную обработку транзакций. Флагманский продукт InterSystems СУБД Caché появилась на рынке в конце 1997 года, став первой в мире СУБД, идеально подходящей для разработки Web-приложений (e-DBMS). Сервер Многомерных Данных и Сервер Приложений обеспечивают высокую производительность и масштабируемость, интегрированный объектный и реляционный доступ к данным и поддержку state-aware Web-приложений. Профессиональные разработчики получают в свое распоряжение мощный инструмент быстрой разработки приложений и гибкость при выборе среды программирования. Клиенты в 88 странах мира используют более чем двадцатилетний опыт InterSystems в разработке СУБД и имеют возможность круглосуточно обращаться в службу поддержки. Объектная модель Caché. Представление объектов реального мира в виде плоских реляционных таблиц в большинстве случаев приводит к потере семантики. Однако, множество компаний, имеющих работающие приложения, построенные на базе реляционных таблиц, не желают переходить на объектно-ориентированную технологию, т.к. это приведет к большим затратам на этапе трансляции. Кроме этого, зависимость приложений от структурированного языка запросов (SQL), также является камнем преткновения при принятии решения о переходе на более развитую объектно-ориентированную технологию. Caché - это высокопроизводительная постреляционная база данных, а также развитая система управления базой данных (СУБД). Основным отличием БД Caché от РБД и ООБД является универсальность представления данных в Caché, реализуемая с помощью т.н. единой архитектуры данных. В рамках этой архитектуры существует единое описание объектов и таблиц, отображаемых непосредственно в многомерные структуры ядра базы данных, ориентированного на обработку транзакций. Имеющиеся серверы Caché Objects
5
и Caché SQL предоставляют в распоряжение разработчика все наиболее популярные интерфейсы, посредством которых и унаследованные реляционные и новые объектно-ориентированные прикладные системы получают равноправный доступ к данным. Кроме реляционного и объектного доступов к данным, разработчику предлагается прямой доступ к данным (Caché Direct), т.е. доступ непосредственно к многомерным структурам ядра. Архитектура Caché приведена на рис. 1. Cachè Server Pages XML ActiveX Java
Единая архитектура данных Cachè Objects
Cachè Direct
Cachè SQL
ODBC JDBC
С++ Ядро СУБД Cachè (TMDMTM)
Другие БД
Рис.1. Архитектура Caché. Независимость хранения данных от способа их представления дает разработчику возможность создавать приложения на языках программирования, поддерживающих как реляционную технологию (ODBC, JDBC), так и объектную (Java, С++, XML и т.д.). При этом нет необходимости создавать промежуточную среду для конвертации из одного формата представления данных в другой - Caché произведет необходимую конвертацию автоматически. Caché Objects. Объектная модель Caché следует рекомендациям по стандарту ODMG (Object Data Management Group). Caché классы в полном объеме поддерживают все основные концепции объектной технологии: • Наследование. Объектная модель Caché позволяет наследовать классы от произвольного количества родительских классов. • Полиморфизм. Объектная модель Caché позволяет создавать приложения целиком и полностью независимыми от внутренней реализации методов объекта. • Хранимость. Объектная модель Caché позволяет долговременно хранить объекты на физических носителях. Поддерживаются несколько форматов хранения объектов – автоматический, предопределенный в Caché; ручной, определенный клиентом; а также Caché может выступать в роле шлюза для хранения данных в виде реляционных таблиц в других БД. Класс объектов в Caché хранится в двух формах: • Описательная форма. Поддерживаются 2 языка описания классов объектов –UDL(unified definition language) и CDL (class definition language). Следует заметить, что UDL поддерживается начиная с версии Caché 5. В работах рекомендуется использовать UDL, т.к. CDL поддерживается для совместимости с предыдущими версиями Caché. • Объектная run-time форма. Использование класса возможно только после его компиляции в объектный код. Для определения классов объектов, а также для решения многих других задач разработки приложений в Caché реализован инструментарий Caché Studio. 6
Caché Studio предоставляет набор интерфейсов для решения следующих задач: 1. Ведение проектов. В Caché 5 введено понятие проекта. Проект объединяет классы, программы и CSP-документы, используемые для решении некоторой прикладной задачи. Caché Studio предлагает набор интерфейсных средств для создания новых проектов, редактирования состава и удаления существующих проектов. 2. Поддержка базы метаданных классов Caché. С помощью Caché Studio возможно создание новых, редактирование и удаление существующих классов, а также добавление и удаление классов в/из проекта. Caché Studio поддерживает два языка описания классов (UDL, CDL) и обеспечивает контекстную и синтаксическую подцветку элементов класса, для удобства работы пользователя. 3. Обеспечение интерфейсами для создания и редактирования программ Caché. Caché Studio поддерживает два языка написания программ Caché – COS и Caché Basic, и обеспечивает контекстную и синтаксическую подцветку составных частей программы. Также Caché Studio предоставляет интерфейсы для добавления программ Caché в проект и их удаления из проекта. 4. Обеспечение интерфейсами для создания и редактирования CSPдокументов. Развитый интерфейс для разработки CSP документов Caché Studio обеспечивает контекстную и синтаксическую подцветку CSP тегов, HTML тегов, COS кода, а также JavaScript. 5. Обеспечение интерфейсами для отладки Caché программ и CSP страниц. Рассмотрим виды классов, а также типы основных элементов классов, поддерживаемых в Caché, на примере создания небольшого приложения в Caché Studio. Как пример, рассмотрим предметную область «Семья». Обычная семья включает в себя Отца, Мать и детей. Определим основные функции разрабатываемого приложения: создать семью; добавить ребенка; изменить характеристики родителей и т.д. План работы: 1. Разработка концептуальной и физической моделей предметной области. 2. Создание Caché проекта. 3. Создание необходимых классов Caché. Примеры работы с классами: создание, удаление, редактирование объектов. 4. Реализация требуемой функциональности с помощью методов класса Caché. Использование методов. Разработка концептуальной и физической моделей предметной области. Для решения поставленной задачи воспользуемся одной из диаграмм UML – диаграммой классов. Для этого определим основные объекты предметной области, их свойства, а также взаимоотношения между выбранными объектами. Основными объектами являются: 1. Отец. 2. Мать. 3. Ребенок. 4. Семья.
7
5. Свидетели. Определим свойства каждого из объектов: Объект Отец
Свойства Фамилия Имя Отчество Дата рождения Паспортные данные Мать Фамилия Имя Отчество Дата рождения Паспортные данные Ребенок Родители Усыновлен? Фамилия Имя Отчество Дата рождения Паспортные данные Свидетель Фамилия Имя Отчество Дата рождения Паспортные данные Кем Приходиться Семья Отец Мать Дети Дата создания Адрес дворца бракосочетания Свидетели Адрес жительства Как можно заметить, некоторые свойства объектов Отец, Мать, Свидетель и Ребенок повторяются. Для исключения хранения избыточной информации введем вспомогательный объект Человек, который будет иметь следующие свойства: Объект Свойства Человек Фамилия Имя Отчество Дата рождения Паспортные данные Пол Для определения связей между выбранными объектами необходимо знать, какие виды классов поддерживаются Caché. Объектная модель Caché поддерживает несколько видов классов (рис.2).
8
Классы типов данных
Незарегистрирова нные классы
Классы
Встраиваем ые классы
Классы объектов Зарегистрирова нные классы
Хранимые классы
Рис.2. Объектная модель Caché Caché классы подразделяются на два типа – классы типов данных и классы объектов. Классы типов данных определяют допустимые значения констант (литералов) и позволяют их контролировать. Классы типов данных могут выступать как системные или предопределенные константы (%Integer, %String и т.д.), так и константы, определенные пользователем. Классы типов данных не могут содержать свойств. Невозможно создать экземпляр класса типов данных, что является главным отличием от классов объектов. Зарегистрированные классы обладают предопределенным поведением, т.е. набором встроенных функций, наследуемых из системного класса %RegisteredObject (следует также заметить, что знак процента определяет принадлежность класса или метода к системному классу) и отвечающих за создание новых объектов и за управление размещением объектов в памяти. Незарегистрированные классы не обладают предопределенным поведением и разработка функций класса целиком и полностью возлагается на разработчика. Встраиваемые и хранимые классы обычно наиболее часто используются в проектах, поэтому рассмотрим их подробнее. Встраиваемые классы. Встраиваемые классы наследуют свое поведение от класса %SerialObject. Основной особенностью хранения встраиваемого класса является то, что в памяти объекты встраиваемых классов существуют как независимые экземпляры, однако могут быть сохранены в базе данных, только будучи встроены в другой класс. Основным преимуществом использования встроенных классов является минимум издержек, связанных с возможным в будущем изменением набора одинаковых свойств классов, представленного в виде встраиваемого объекта. Вернемся к нашему примеру. Нет необходимости хранить экземпляры класса Человек независимо в БД, свойства этого класса нам нужны только как составная часть объектов классов Отец, Мать и Ребенок. Поэтому, класс Человек является встраиваемым классом в вышеперечисленные классы. Хранимые классы. Хранимые классы наследуют свое поведение от класса %Persistent. Класс %Persistent предоставляет обширный набор функций своим наследникам, включающий создание объекта, подкачку объекта из БД в память, удаление объекта и т.д. Определимся с уникальной идентификацией объектов хранимых
9
классов в памяти и в БД. Каждый экземпляр (объект) класса имеет 2 уникальных идентификатора – OID и OREF. OID (object ID) уникально идентифицирует объект, в таблице размещения объектов БД, т.е. на физическом носителе, а OREF (object reference) уникально идентифицирует объект, который был подкачен из БД и находится в памяти компьютера. В нашем примере класс Семья является хранимым – нам необходимо хранить экземпляры класса Семья в БД независимо от других классов. На рис.3. приведена разрабатываемой системы.
концептуальная модель предметной области Человек +ФИО +Паспорт +ДатаРождения +Пол +РасчитатьВозраст()
«uses»
«uses»
«uses» Ребенок
Свидетели
+Усыновлен +ОбщиеДанные : Человек +Печатать()
+Адрес +ОбщиеДанные : Человек +КемПриходится +Печатать()
*
Семья
-Дети -Родители 1
+ДатаСоздания +РегистрацияВ +АдресЖительства +Свидетели : Свидетели +Отец : Человек +Мать : Человек +ДобавитьРебенка() +УдалитьРебенка() +ВывестиСписокДетей() +ДобавитьСвидетеля() +УдалитьСвидетеля() +ВывестиСписокСвидетелей()
«uses»
Рис.3. Диаграмма классов 2. Создание Caché проекта. Для создания проекта необходимо запустить утилиту Caché Studio, которую не трудно найти в меню Caché-куба. Для разграничения доступа к данным в БД Caché предусмотрена процедура авторизации пользователя. Выберите требуемое соединение (Local), область (User), введите имя пользователя(_system) и пароль(SYS) для начала работы.
10
Соединение
Область
Имя пользователя Пароль
Рис.4. Авторизация пользователя. При успешном завершении процедуры авторизации становится активной основная среда разработки. На рис.5. приведен внешний вид Caché Studio, а также названия основных составных частей. Главное меню
Стандартная панель
Панель мастеров
Область редактирования Область проекта
Панель отладки
Область инспектора
Область информации
11
Caché Studio обладает широкими возможностями, однако рассмотрим только те, которые являются отличными от стандартных возможностей Windows-приложений, на примере создания приложения Семья. Создадим класс Человек и добавим его в проект. Класс в Caché Studio можно создать либо вручную, используя конструкции UDL, либо автоматически, используя Class Wizard. Для вызова Class Wizard необходимо выбрать пункт меню File->New; нажать комбинацию клавиш Ctrl-n; либо нажать на пиктограмме, изображенной ниже:
Затем, в появившемся окне NEW необходимо выбрать элемент проекта, подлежащий созданию:
Выбираем Caché Class Definition и нажимаем ОК. На экране появляется первый шаг мастера классов. На первом шаге мастера классов указываются общие сведения о создаваемом классе – имя пакета, имя класса и комментарии. Если имя пакета не определено в БД, тогда Caché создаст новый пакет автоматически. Указываем имя пакета – Family, имя класса – Human, комментарии – Общие данные о человеке и переходим к следующему шагу. На втором шаге мастера классов указывается вид класса. Виды классов, поддерживаемые объектной моделью Caché, описаны выше. Следует только выделить класс CSP page, при помощи которого можно создавать Web приложения для работы с данными из БД Caché. Особенности этого класса будут рассмотрены подробнее ниже. Класс Человек является встраиваемым, поэтому выбираем вид Serial и переходим на следующих шаг. В Caché реализована возможность популяции класса, т.е. реализованы методы для генерации тестовых данных объектов класса. Эти методы наследуются из системного класса %Populate. Кроме этого, в Caché 5. включена поддержка импорта данных из XML документов в Caché и наоборот экспорта объектов Caché в XML документы. Методы, реализующие работу с XML данными, определены в системном классе %XML.Adaptor и будут рассмотрены 12
подробнее ниже. Следующий шаг мастера классов позволяет включить поддержку популяции класса и поддержку XML импорта/экспорта. Завершаем создание класса нажатием кнопки “Finish”. Окна мастера классов приведены в приложении 1. По завершению создания класса рекомендуется сохранить его в БД. Это осуществляется путем нажатия клавиш Ctrl-S, либо выбором пункта меню Files>Save. Описание только что созданного класса, записанное в конструкциях языка UDL, находится в Области Редактирования. Создадим свойства класса Человек и на примере созданного класса рассмотрим основные конструкции языка UDL. Для создания новых свойств в Caché Studio имеется мастер свойств, который вызывается либо из пункта меню Class->Add->New Property; либо нажатием на следующую пиктограмму:
На первом шаге мастера свойств указываются общие сведения о создаваемом свойстве – имя свойства и комментарии. Вводим FIO в поле имени и «ФИО человека» в качестве комментария. С помощью следующего шага мастера свойств можно указать вид создаваемого свойства. В Caché поддерживаются несколько видов свойств: • Константы. Простые типы данных (%String, %Integer, %Date и т.д.), которые наследуют свое поведение от класса типов данных. • Ссылки на объекты. Каждый класс объектов может рассматриваться как сложный тип данных. Caché автоматически осуществляет подкачку объектов в память и доступ к элементам объектов осуществляется через точечный синтаксис. • Встроенные объекты. Функционируют аналогично ссылке на объект. Существенное различие заключается в том, что в качестве типа данных задается не хранимый, а встраиваемый класс объектов. • Потоки данных (Binary or Character Large Object – BLOB or CLOB) большое неструктурированное множество данных. В Caché различают два типа потоков данных – BINARYSTREAM (состоящие из двоичных данных) и CHARACTERSTREAM (состоящие из символов). При этом двоичный поток данных может быть использован для хранения больших объемов двоичных данных (>32Kb), таких как картинок, а символьный поток данных может быть использован для хранения больших объемов текстовых данных (>32Kb), таких как главы в книге. • Коллекции. Достоинством объектно-ориентированных БД является возможность хранить множество значений в одном свойстве. В Caché поддерживаются два типа коллекций – массив и список. Каждый элемент массива обладает индексом, который уникально характеризует элемент в массиве, в то время как в списке элемент уникально определяется по номеру позиции в списке. • Связи. Связи представляют собой двунаправленные зависимости между хранимыми объектами. В Caché реализовано 2 типа связей – Parent – Child (зависимая связь, т.е. при удалении предка, автоматически удаляются наследники) и One-Many (независимая связь - удаление предка при существовании наследников приводит к ошибке).
13
В нашем классе ФИО является простым типом данных или константой, хранящей данные в виде строки символов. Поэтому определим тип как Single value of type: %String и перейдем на следующий шаг. На следующем шаге мастера свойств определяются характеристики свойства. Required – свойство с такой характеристикой обязательно должно иметь значение. Indexed - на основе этого свойства создается индекс в таблице БД. Unique – значения такого свойства должны быть уникальны в БД.Calculated – данное свойство является вычисляемым (производным) и его значение не хранится перманентно в БД, а рассчитывается из значений других свойств. SQL Field Name – данная характеристика не обязательна, она служит для определения имени свойства в запросе SQL (по умолчанию принимается имя свойства). Свойство FIO не имеет этих характеристик, поэтому переходим к следующему шагу. На следующем шаге определяются параметры свойства. С помощью параметров можно контролировать допустимые значения свойств. К примеру, MAXLEN или MINLEN задают соответственно максимально допустимую или минимально допустимую длину значения свойства. Зададим для свойства FIO MAXLEN=200. На следующем шаге мастера свойств можно переопределить методы работы со значением свойства, соответственно метод Get и метод Set. Нет необходимости переопределять методы для свойства FIO, воспользуемся стандартными методами предоставляемыми Caché. Завершаем работу мастера свойств нажатием кнопки Finish. Самостоятельно создайте оставшиеся свойства класса Human, а также другие классы предметной области Семья. Характеристики свойств и классов приведены в табл.1.
Класс Человек Характеристики класса Пакет Family Имя класса Human Комментарии Общие данные о человеке Класс-предок (вид %SerialObject класса) Свойства класса Имя свойства Комментарии Вид свойства
FIO ФИО человека %String
Параметр
MAXLEN=200
Имя свойства Комментарий Вид свойства Параметр
Passport Паспортные данные или данные заменяющего документа. %String MAXLEN=200
Имя свойства
DofB
Встраиваемый класс, может быть сохранен только внутри хранимого (%Persistent) класса
Константа, хранящая строку символов. Максимально допустимая длина хранимой строки
14
Комментарий Вид свойства
Дата рождения %Date
Имя свойства Комментарий Вид свойства
Sex Пол человека %Boolean
Дата хранится в Caché в виде количества дней прошедших с 31.12.1840. Получить текущую дату можно с помощью $zdt(+$h).
Булева переменная может принимать два значения 0 и 1. 0 – мужской, 1 – женский.
Класс Ребенок Характеристики класса Пакет Family Имя класса Baby Комментарии Данные о детях Класс-предок (вид %Persistent класса) Свойства класса Имя свойства Комментарии Вид свойства
Adopt Усыновлен ? %Boolean
Имя свойства Комментарий Вид свойства
Personal Персональные данные Family.Human
Хранимый класс. Данные хранятся непосредственно в БД.
Ссылка на встраиваемый объект
Класс Свидетель Характеристики класса Пакет Family Имя класса Witness Комментарии Сведения о свидетелях. Класс-предок (вид %Persistent класса) Свойства класса Имя свойства Address Комментарии Контактные данные Вид свойства Character Stream Имя свойства Комментарий Вид свойства
Personal Персональные данные Family.Human
Имя свойства Комментарии Вид свойства
Related Кем приходится? %String
Неструктурированные символьные данные (BLOB).
Ссылка на встраиваемый объект
15
Параметр
VALUELIST = ",мать,отец,друг мужа, друг жены, друг"
Список допустимых значений. Первый символ определяет разграничитель (,)
Класс Семья Характеристики класса Пакет Family Имя класса Family Комментарии Сведения о семье. Класс-предок (вид %Persistent класса) Свойства класса Имя свойства CreationDate Комментарии Дата создания семьи Вид свойства %Date Параметр InitialExpression = {+$h} Имя свойства Комментарий Вид свойства Параметр
RegistratedIn Орган, зарегистрировавший брак. %String MAXLEN=200
Имя свойства Комментарии Вид свойства Параметр
Address Адрес местожительства %String MAXLEN=200
Имя свойства Комментарии Вид свойства
Witnesses Свидетели брака Array of Family.Witness
Имя свойства Комментарии Вид свойства
Father Отец семейства Family.Human
Имя свойства Комментарии Вид свойства
Mother Мать семейства Family.Human
По умолчанию дата создания семьи равна системной дате
Коллекция типа массив хранимых объектов. В массиве хранятся ссылки на объекты (OID) класса Family.Witness
Таблица. 1. Рассмотрим процесс определения отношений между классами, с использованием мастера свойств. Отношение – это двусторонняя связь между классами, поэтому определить отношение в Caché можно из любого класса – будь то класс-родитель или класс-потомок. 16
Для примера создадим отношение между классами Семья и Ребенок. Отношения, как было сказано ранее, могут быть либо независимыми (один-комногим), либо зависимыми (родитель-потомок). Каждая сторона в отношении имеет мощность. В Caché реализованы мощность типа 1:М(независимое) и Parent-Children(зависимое), однако предоставляется возможность самостоятельного создания отношений любой мощности. В нашем случае отношение зависимое Parent-Children. Перед созданием отношения нет необходимости создавать оба класса – класс-предок(Family.Family) и класс-потомок (Family.Child), мастер свойств предложит создать несуществующий класс автоматически. Создадим отношение со стороны класса-предка, для это открываем описание класса Family.Family из области проекта. Отношение определяется на этапе «Выбор типа свойства» мастера свойств. На данном этапе необходимо выбрать тип свойства=Relationship и перейти на следующий этап. Здесь, в поле имя класса вводится имя класса на другой стороне отношения (Family.Baby), определяется его свойство (Parent), ответственное за отношение и мощность отношения (1:М или Parent-Children). Следующий этап мастера свойств предлагает при необходимости создать требуемый класс, свойство или индекс. Необходимо преобразовать описательную форму класса в объектную. Для этого вызываем компилятор класса путем нажатия комбинации клавиш Ctrl-F7 или выбора пункта меню Build->Compile. Необходимо также сохранить проект. Для этого выберите пункт меню File>Save Project, введите имя проекта(Family) и нажмите кнопку ОК. Основные конструкции UDL. Язык описания классов UDL - это новая разработка корпорации Intersystems, анонсированная в версии 5. Конструкции UDL и CDL не совместимы, однако Caché обеспечивает интерфейсы для работы с обоими языками описания классов. В проектах рекомендуется использовать UDL. Рассмотрим основные конструкции языка UDL. Для описания классов используется следующая конструкция: Class Package.Class1 Extends (PCl1, PCl2,…) [ Param1 = value, Param2 =value] { } Ключевое слово Class задает начало определения класса Class1 пакета Package. В круглых скобках, следующих за ключевым словом Extends, через запятую перечисляются классы-предки. В квадратных скобках перечисляются параметры класса, к примеру [ClassType = persistent, Owner = _SYSTEM, SqlTableName = _class1]. Для начала определения свойства используется ключевое слово Property: Property P1 As %String(P1 = value,…) [charact1=value,…]; P1 – имя свойства. Ключевое слово As служит для указания класса данных свойства. В круглых скобках определяются параметры свойства (MAXLEN=100), а в квадратных – характеристики (Calculated). Для определения метода класса используется конструкция, которая начинается с ключевого слова Method:
17
Method Method1(Arg1 As %Library.String) As %Integer [ Private ] { q } В круглых скобках перечисляются формальные аргументы метода, а также их классы типов данных или классы объектов. Ключевое слово As определяет тип возвращаемого методом значения. В квадратных скобках перечисляются параметры класса. Тело метода заключается в фигурные скобки. Для редактирования элементов класса, а также характеристик самого класса можно воспользоваться возможностями, предоставляемыми инспектором классов. Для удобства в Caché Studio реализована контекстная и синтаксическая подцветка основных конструкций языка UDL. Использование экземпляров класса. Рассмотрим основные принципы работы с объектами классов Caché. Для этого воспользуемся утилитами Caché Terminal и Caché Explorer. Caché Terminal – это программа эмуляции ASCII терминала и обычно используется для целей тестирования правильности работы приложения. Хранимый класс (наследуемый от системного класса %Persistent) Caché предоставляет набор методов для работы с объектами. Эти методы включают: метод %New() – для создания нового объекта класса в памяти, метод %OpenId(OID) – для подкачки существующего объекта в память, метод %Delete(OID) – удаление объекта из БД, метод %Save() – сохранение объекта в БД, %Close() – удаление проекта из памяти. Рассмотрим использование методов на примерах работы с классами пакета Family. Для создания нового экземпляра семьи воспользуемся методом %New класса Family, наследуемым из системного класса %Persistent. USER> set cl=##Class(Family.Family).%New() USER> – это приглашение Caché Terminal, указывающее имя активной области (USER). set – команда COS(Caché Object Script), предназначенная для присваивания значения переменной. cl – имя локальной переменной, которой присваивается OREF нового объекта класса. ##Class(Family.Family) – макровызов, служащий для создания ссылки на методы класса или на объекты. %New() – Символ % определяет принадлежность метода New к системному классу. С помощью предыдущей команды мы создали новый экземпляр класса Family.Family, OREF которого хранится в локальной переменной сl. Далее присвоим свойству класса Family Address адрес местожительства: USER>set cl.Address="ул.Юных Ленинцев, 35" Для обращения к свойствам и методам объекта в Caché используется точечный синтаксис. Присваиваемое свойству Address значение должно быть заключено в двойные кавычки. Далее определим отца семейства. Свойство Father является встроенным объектом, для обращения, к свойствам которого необходимо использовать каскадный точечный синтаксис: USER>set cl.Father.FIO="Иван Иванович Иванов" USER>set cl.Father.DofB=$zdh("12/26/1970")
18
Первой командой присваиваем свойству FIO встроенного объекта строку символов. Второй командой, используя встроенную функцию преобразования строки символов во внутреннее представление даты $zdh(), свойству DofB присваиваем дату рождения Ивана Ивановича – 26 декабря 1970 года. Подобным образом определяются все константы класса Family и свойства встроенного объекта. Определим свидетелей свадьбы. Свойство Witnesses является массивом объектов. Системный класс %AbstractArray предоставляет ряд функций для работы с элементами массива: Count() – возвращает количество элементов массива, SetAt(value,index) – добавляет новый элемент в ячейку массива с индексом index, GetAt(index) – извлекает элемент массива с индексом index, Next(index) – возвращает индекс следующего элемента массива и т.д. В нашем примере индексом массива будет принадлежность свидетеля к жениху или невесте. Массив объектов не хранит сами объекты, хранению подлежат ссылки на эти объекты (OID). Поэтому необходимо создать объект Witness, сохранить его в БД и записать OID созданного объекта в ячейку массива. USER>set wit=##Class(Family.Witness).%New() USER>do wit.Address.Write("Россия, Москва, Ленинский проспект, д.10, кв.10") USER>set wit.Related="друг" USER>set wit.Personal.FIO="Петр Петрович Петров" USER>write $$DisplayError^%apiOBJ(wit.%Save()) 1 Первой строкой создан новый экземпляр класса. Вторая строка добавляет в СLOB данные об адресе свидетеля, для этого используется метод Write() системного класса %AbstractStream. Свойство Related имеет ограниченное параметром VALUELIST количество допустимых значений, указание значений, не определенных параметром VALUELIST приведет к ошибке при сохранении объекта. Далее, используя точечный синтаксис, происходит обращение к свойствам встроенного объекта Human. Последней строкой мы сохраняем созданный экземпляр в БД, используя метод %Save() и декодируем результат операции с помощью системной функций $$DisplayError^%apiOBJ. Добавляем экземпляр класса Witness в список свидетелей свадьбы и удаляем его из памяти с помощью метода %Close(): USER>do cl.Witnesses.SetAt(wit,"Жених") USER>do wit.%Close() Далее добавим ребенка в семью. Как вы помните, между классом Family и Baby определена двунаправленная связь. Множественная сторона отношения в памяти ведет себя так же, как и коллекции объектов. Рассмотрим добавление связанного объекта: USER>set child=##Class(Family.Baby).%New() USER>set child.Personal.FIO="Василий Иванович Иванов" USER>set child.Adopt=0 USER>set child.Parent=cl Последняя команда определяет принадлежность объекта-ребенка объектуродителю. Ту же операцию можно сделать и со стороны объекта-родителя: USER>do cl.Children.Insert(child) Далее сохраняем объект Family в БД и удаляем его из памяти (НЕ ЗАБЫВАЙТЕ УДАЛЯТЬ ОБЪЕКТЫ ИЗ ПАМЯТИ): USER>write $$DisplayError^%apiOBJ(cl.%Save()) 1 USER>do cl.%Close()
19
Следующим образом можно открыть объект БД и подкачать его, а также связанные с ним объекты в память: USER>set cl=##Class(Family.Family).%OpenId(1) %OpenId(OID) – это метод класса %Persistent, аргументом которого является OID объекта в БД. Локальной переменной cl теперь присвоено значение OREF объекта в памяти. Далее выводим значения свойств открытого объекта в окне Caché Terminal: USER>write cl.Address ул.Юных Ленинцев, 35 USER>write $zdt(cl.CreationDate) 08/26/2001 Caché автоматически подкачивает связанные объекты, как встраиваемые: USER>write cl.Father.FIO Иван Иванович Иванов так и объекты по ссылке: USER>write cl.Witnesses.GetAt("Жених").Related friend USER>write cl.Witnesses.GetAt("Жених").Personal.FIO Петр Петрович Петров так и объекты связанные двунаправленной связью (отношением): USER>write cl.Children.GetAt(1).Adopt 0 USER>write cl.Children.GetAt(1).Personal.FIO Василий Иванович Иванов Закрываем открытый объект: USER>do cl.%Close() Удалить объект из БД Caché можно с помощью метода %DeleteId(): USER>write ##Class(Family.Family).%DeleteId(2) 1 Рассмотрим особенности хранения объектов БД Caché. Объекты в БД Caché хранятся в виде многомерных структур. Многомерность данных в Caché реализуется через индексы переменных. Существует два типа переменных в Caché – локальные и глобальные. Локальные переменные доступны только в том процессе, где они инициированы. Глобальные переменные или глобали носят смысловую нагрузку, отличную от глобальных переменных во многих языках программирования (С++, JAVA). Глобальные переменные в Caché доступны всем процессам, однако, они не являются временными переменными, а являются длительно хранимыми структурами данных или единицами хранения данных. Наличие знака циркумфлекса (^) определяет глобаль. Рассмотрим примеры локальных переменных и глобалей: Определяем скалярную локальную переменную: USER>set var1=”abc” Переменную var1 можно использовать в текущем процессе, однако она не будет доступна другим процессам: USER>set var1=”abc”_”def” С помощью write без аргументов можно вывести все локальные переменные текущего процесса: USER>write var1=”abc” Удалить локальную переменную можно с помощью комманды kill:
20
USER>kill var1 USER>write kill без аргументов удаляет все локальные переменные для активного процесса. Теперь определим скалярную глобаль: USER>set ^var1=”abc” USER>write Write без аргументов выводит только локальные переменные, однако если указать имя глобали, то write выведет ее значение: USER>write ^var1 abc С помощью kill можно удалить глобаль, если полностью указать ее имя: USER>kill ^var1 Многомерные локальные переменные и глобали определяются следующим образом: USER>set var1("abc",123)=1 USER>set ^var2("abc",123)=1 Для многомерных переменных также применима функция kill. Полезной функцией при работе с переменными является функция $Data(переменная). С помощью этой функции можно определить, существует переменная или нет. Результатом могут быть следующие значения: 0 или 10 – переменная с данными индексами не существует; 1 или 11– переменная существует и содержит данные. Пример, USER>kill USER>set a=10 USER>write $D(a) 1 USER>set ^a(1,"abc")=1 USER>write $Data(^a) 10 USER>write $Data(c) 0 USER>set ^a(1,"abc","def")=1 USER>write $Data(^a(1,"abc")) 11 Другой полезной функцией является $Get(переменная, Х). При существовании переменной возвращается ее значение, иначе возвращается Х. Данные свойств объектов хранятся в виде глобалей, имена которых имеют следующий вид: ^Пакет.КлассD – для хранения данных; ^Пакет.КлассI – для хранения индексов: ^Пакет.КлассS – для хранения BLOB и CLOB. С помощью утилиты Caché Explorer можно получить прямой доступ к многомерным структурам ядра БД Caché. Caché Explorer предоставляет пользователю ряд функций, включающий функции просмотра, удаления и редактирования элементов структур, а также функции импорта, экспорта глобалей, программ и классов Caché и многие другие функции. Внешний вид утилиты приведен на рис.7.
21
Рис.7. Caché Explorer Каждой области (namespace) соответствуют 3 вложенные папки: папка Глобали, папка Программы и папка Классы. Каждая из этих папок содержит соответственно список глобалей (или глобальных переменных), список классов и список программ, относящихся к выбранной области. Нажатие правой кнопки мыши на одном из элементов списков вызывает контекстное меню, с функциями редактирования, импорта/экспорта и многими другими. Создание методов классов. До сих пор мы изучали изменение состояния объектов, т.е. изменение значений свойств экземпляров. Однако, объект обладает не только состоянием, но и поведением. Определим функции системы и реализуем их с помощью методов классов и объектов. Необходимо понимать разницу между методами классов и методами объектов. Методы объекта или экземпляра всегда вызываются для определенного экземпляра класса, ссылку на который они неявно получают. В противоположность методам экземпляра, методы класса не вызываются для определенного экземпляра и не имеют доступа к свойствам или методам экземпляров, однако имеют доступ к параметрам классов. Характерным примером метода класса является метод %New(), который не применим к экземпляру класса, т.к. порождает его. Метод объекта как и метод класса, обладает однозначным именем и списком формальных аргументов. Используя формальные аргументы и алгоритм, реализуемый кодом метода, метод возвращает однозначное значение заданного типа. В объектной модели Caché реализованы четыре разновидности методов: • Метод-код; • Метод-выражение; • Метод-вызов;
22
• Генератор методов. Наиболее часто используемыми разновидностями методов в разрабатываемых проектах являются метод-код и метод-выражение. Метод-код содержит код, написанный на COS или Caché BASIC, который при компиляции преобразуется в программу Caché. Созданная программа вызывается каждый раз при обращении к методу класса или методу объекта. Метод-выражение содержит одно выражение, результат выполнения которого является выходным значением метода. Изучим основные структурные элементы и функции языка COS, а также принципы работы с методами на примере реализации функциональных требований предметной области «Семья». План работы: 1. Открытие проекта Caché. 2. Использование мастера методов для создания метода РассчитатьВозраст(CalculateAge) класса Человек (Human). 3. Создание оставшихся методов используя Caché Studio. 4. Примеры использование методов в Caché Terminal. Открытие проекта Caché. Запустите Caché Studio. После успешного прохождения процедуры авторизации необходимо выбрать пункт меню File->Open Project или нажать комбинацию клавиш Ctrl+Shift+O. В появившемся окне открытие/создание проекта (см. рис. 8)необходимо выбрать имя соединения (Local), область (User), имя проекта (Family) и нажать кнопку ОК. Выбранный проект загружается в область Caché Studio, и можно приступать к реализации функциональной части классов.
23
Рис.8. Окно открытия проекта. Создадим метод CalculateAge класса Family.Human с помощью мастера методов. В области проекта выбираем папку Классы, пакет Family и класс Human. Запустить мастер методов можно либо выбрав пункт меню Class->Add>New Method, либо нажав на следующую иконку:
Первый шаг мастера методов определяет общие данные о создаваемом методе – имя метода (CalculateAge) и комментарии (Рассчитать возраст человека). С помощью следующего шага можно определить тип возвращаемых методом данных (%Integer), а также список формальных параметров (отсутствуют). Характеристики метода определяются на третьем шаге мастера методов. Методы типа Private могут быть вызваны только из других методов экземпляра или методов класса. Методы типа Final не могут быть переопределены в классах-наследниках. Метод класса определяется выставлением флажка Class Method. Метод класса также может быть представлен в реляционном таблицах, как хранимая процедура (SQL Stored Procedure). Создаваемый метод является общедоступным методом экземпляра, поэтому не выставляем никаких флажков и переходим на следующий шаг.
24
Код метода определяется на следующем шаге. Особенностью написания Caché программ или методов является то, что первый символ в каждой строке определяет начало имени метки внутри кода. Поэтому, код метода должен начинаться со второго символа, если это не метка. Рассчитаем возраст человека по следующей формуле: quit $H-..DofB\365. $H – это системная функция, возвращающая системную дату и время в виде двух чисел, разделенных запятой. Первое число определяет количество дней, прошедших с 31.12.1840. Второе число хранит количество секунд, прошедших с 00.00. С помощью конструкции ..DofB мы обращаемся к свойству экземпляра, из которого вызывается метод CalculateAge. Обратный слеш (\) – это оператор COS, служащий для деления без остатка. С помощью команды quit выходим из метода и возвращаем значение метода, определяемое аргументом quit. Вводим код метода в окно мастера методов и завершаем работу мастера, нажатием кнопки Finish. Сохраняем класс и компилируем его в объектный код. В табл.2. приведено описание методов, которые необходимо создать самостоятельно. Характеристики метода Значение Код метода и описание w !,"------------------------------" Family.Baby Класс w !,"ФИО ребенка:"_..Personal.FIO FormatData Название w !,"Дата рождения:"_..Personal.DofB Форматирование w !,"Возраст:"_..Personal.CalculateAge() Комментарий данных w !,"Паспорт:"_..Personal.Passport w !,"Пол:"_..Personal.Sex Нет Аргументы w !,"Усыновлен:"_$s(..Adopt=1:"да",1:"нет") %Boolean Тип возвращаемого значения w !,"------------------------------" Нет Параметры quit 1 w{rite}-вывод строки символов на текущее устройство, ! – Комментарии перевод строки и возврат каретки (CRLF), ..Property – значение свойства активного экземпляра, $s(cond1:value1,cond2:value2, 1:defaultvalue) – многозначное условие - если cond1=1, то вернуть value1 и т.д. quit 1 – возвращаемое значение Класс Название Комментарий Аргументы Тип возвращаемого значения Параметры Комментарии Класс Название Комментарий
Family.Witness FormatData Форматирование данных Нет %Boolean Нет
w !,"------------------------------" w !,"ФИО свидетеля:"_..Personal.FIO w !,"Дата рождения:"_..Personal.DofB w !,"Возраст:"_..Personal.CalculateAge() w !,"Паспортные данные:"_..Personal.Passport w !,"Пол:"_..Personal.Sex w !,"Адрес:"_..Address.Read(100) w !,"Отношение:"_..Related w !,"------------------------------" quit 1
..Address.Read- метод класса %AbstactStream, считывающий заданное количество символом из BLOB Family.Family AddChild Добавление ребенка
n child s child=##Class(Family.Baby).%New() if child=$$$NULLOREF w !,"Error.New" quit 0 s child.Personal.FIO=FIO
25
Аргументы
Тип возвращаемого значения Параметры Комментарии
Класс Название Комментарий Аргументы Тип возвращаемого значения Параметры Комментарии
Класс Название Комментарий Аргументы
s:DofB'="" child.Personal.DofB=DofB FIO - %String, s child.Personal.Passport=Passport DofB - %Date, s child.Personal.Sex=Sex Passport - %String, s child.Adopt=Adopt Sex - %Boolean, s child.Parent=cl Adopt - %Boolean if '+child.%Save() w !,"Error.Save" quit 0 if '+child.%Close() w !,"Error.Close" quit 0 %Boolean quit 1 Нет n{ew}- Создание локальной переменной для метода, предыдущее значение сохраняется и восстанавливается после выхода из метода. Каждая локальная переменная метода должна быть инициализирована с помощью new. Причина - локальные переменные методов могут перекрывать друг друга, т.к. порождены в одном процессе. If <expr>[,<expr>…]{code} – Условная конструкция. ElseIf <expr> {code} Else {code} ‘ – отрицание. $$$NULLOREF – макрос, автоматически заменяется при компиляции некоторым значением. Используется для определения правильности создания экземпляра класса в памяти. Системная библиотека макросов %occInclude. s{et}:<expr> - предусловие, оператор set выполнится только в случае истинного значения <expr>. Применимо для некоторых операторов COS – write, quit и т.д. +child.%Save()-преобразование типа данных. child.%Save() возвращает строку – это либо 1, в случае успешного завершения, либо «0 код ошибки» в случае ошибки. Операция сложения (+) применяется исключительно к числовым значениям, поэтому происходит преобразование строки в число, при этом берутся все числа до первого символа. Тоже происходит и с +child.%Close(). ni Family.Family for i=1:1:..Children.Count() { DisplayChildren w !,"Номер - ",i Вывод d ..Children.GetAt(i).FormatData() информации о } quit 1 детях Нет %Boolean Нет ..Children.Count()- метод класса %RelationshipObject, возвращающий количество зависимых объектов в отношении. ..Children.GetAt(i) – метод класса %RelationshipObject, возвращающий ссылку (OREF) на i-элемент в коллекции.
Family.Family DeleteChild Удаление данных о ребенке Нет
n number if ..Children.Count() { d ..DisplayChildren() w !,"Введите номер удаляемого ребенка (0отмена):" r number
26
Тип возвращаемого значения Параметры
%Boolean Нет
if number=0 quit 1 d ..Children.RemoveAt(number) } else { w !,"***Детей нет***" } quit 1
d ..DisplayChildren()- вызов метода активного экземпляра. r{ead} number – считать строку с текущего устройства и поместить в переменную number. d ..Children.RemoveAt(number) – метод класса %RelationshipObject. Удаляет элемент на number- позиции из коллекции. Таблица 2. После добавления методов классы необходимо сохранять и компилировать. Примеры использования созданных методов: USER>s cl=##Class(Family.Family).%New() USER>s cl.Father.FIO="Иванов Иван Иванович" USER>s cl.Mother.FIO="Иванова Любовь Владимировна " USER>d cl.AddChild("Иванов Петр Иванович",+$h,"Паспорт") USER>d cl.DisplayChildren() Номер - 1 -----------------------------ФИО ребенка:Иванов Петр Иванович Дата рождения:08/31/2001 Возраст:0 Паспортные данные:Паспорт Пол:1 Усыновлен:нет -----------------------------USER>d cl.DeleteChild() Номер - 1 -----------------------------ФИО ребенка:Иванов Петр Иванович Дата рождения:08/31/2001 Возраст:0 Паспортные данные:Паспорт Пол:1 Усыновлен:нет -----------------------------Введите номер удаляемого ребенка (0-отмена):1 USER>d cl.DeleteChild() ***Детей нет*** USER>d cl.%Save() USER>d cl.%Close()
Комментарии
Использование SQL и Dynamic SQL. Как было сказано ранее Caché хранит данные в виде многомерных структур и позволяет представлять данные в виде реляционных таблиц. Caché поддерживает все элементы ANSI-стандартов, существующие для SQL и SQL92. Обращаясь через предоставленные ODBC/JDBC драйвера к БД Caché можно запрашивать данные, удовлетворяющие некоторым условиям (DQL),
27
манипулировать данными (DML), либо создавать новые или изменять существующие таблицы (DDL). На примерах изучим принципы работы с данными Caché используя конструкции SQL. Для начала необходимо создать учетную запись ODBC драйвера. Во время инсталляции Caché автоматически создаются две учетных записи – для области USER и области SAMPLES. Если необходимо создать новую учетную запись, то вызывается ODBC менеджер (odbcad32) и проходится стандартная процедура создания учетной записи, используя драйвер InterSystems ODBC. Используя любой SQL-клиент (например, WinSQL) создадим новый класс Caché: create table SQLTable (Prop1 %String, Prop2 %Integer) Создадим новую запись в созданной таблице: insert into SQLTable(Prop1,Prop2) values (“Some String”,1234) Теперь запросим данные из таблицы SQLTable: select * from SQLTable Как видно из примера работать с данными из Caché можно точно также, как и с данными из реляционных БД. Кроме внешнего SQL интерфейса, в Caché программах можно использовать встроенный SQL и создавать динамические запросы. Встроенный SQL не будет часто использоваться в разрабатываемых проектах, поэтому оставляется на самостоятельное изучение. Рассмотрим подробнее принципы работы динамических запросов, а также область их применения. OID объектов, по умолчанию, является автоинкрементальным полем и иногда возникают трудности нахождения определенного OID объекта или создания списка OID некоторого класса, удовлетворяющих некоторым критериям. Для решения подобных задач можно воспользоваться методами системного класса %ResultSet, с помощью которых можно создавать динамические запросы. Рассмотрим создание динамического запроса, для получения OID объектов класса Family.Family : Создаем экземпляр класса %ResultSet и аргументом метода %New определяем динамический запрос: Set result=#Class(%ResultSet) .%New(“%DynamicQuery:SQL”) Далее, аргументом метода Prepare() задаем SQL запрос: Do result.Prepare(“Select ID from Family.Family”) Затем, выполняем SQL запрос методом Execute(): Do result.Execute() В памяти создается структура данных типа список, к элементам которой необходимо обращаться используя методы Next() и Get(ИмяПоляSQLЗапроса): For Quit:’result.Next() { Write result.Get(“ID”) } Do result.%Close() Для получение полной документации о методах класса %ResultSet, а также способах создания динамических запросов, обращайтесь к документации класса %ResultSet. Обработка ошибок в COS. Бывают случаи, когда необходимо обработать ошибку, возникшую в случае непредвиденных обстоятельств. Например, операция w 1/I, при отсутствии проверки I на равенство нулю, возвратит ошибку и прервет процесс
28
выполнения программы. В COS реализованы два способа вызова обработчика ошибок в случае возникновения ошибки: • $ZTrap=”ErrProcCode”. С помощью системной переменной $ZT можно указать строку(ErrProcCode), на которую в случае возникновения ошибки переходит и управление и обработка. • $ETrap=”COSStatement”. В случае возникновения ошибки выполняется выражение COS (COSStatement), указанное как значение системной переменной $ETrap. Код последней ошибки хранится в системной переменной $ECode в виде ANSI Х11.1 стандарта описания ошибки и в системной переменной $ZError, содержащей наименование ошибки и ее месторасположение. Пример: 1. $ZTrap. Abc(I) S $ZT=”ErrHandl” W 1/I Q ErrHandl W !,”$EC = ”_$EC W !,”$ZE = ”_$ZE В Caché Terminal: USER>d ^T1(0) $EC = ,M6,M9, $ZE =
Abc+2^T1 2. $ETrap. Abc(I) S $ET="w !,""$EC=""_$EC,!,""$ZE=""_$ZE s $EC="""" " W 1/I Q В Caché Terminal: USER>d ^T1(0) $EC=,M9, $ZE=Abc+2^T1 Обратите внимание, что при использовании $ET необходимо обнулять значение системной переменной $EC. В разрабатываемых проектах рекомендуется определять обработчики ошибок в методах, где неправильное значение переменных может привести к прерыванию процесса выполнения метода. XML экспорт/импорт. В Caché 5. включена поддержка импорта данных из XML документов в объекты Caché и экспорта данных из объектов Caché в XML документы. Кроме этого, разработчику предоставляется COS-интерфейс к SAX парсеру Apache Xerces 1.4., для решения специфических задач манипулирования данными из XML документов. Универсальность представления данных в Caché, а конкретнее возможность представления данных в виде объектов, позволяет экспортировать объекты Caché в XML документы с минимумом затрат. Рассмотрим возможности Caché по экспорту данных в XML документы. Экспорт данных.
29
Объектная модель Caché позволяет создавать XML документы напрямую либо из программ Caché: write "" write "",book.title, "" либо из CSP страниц: #(book.title)# Рассмотрим экспорт данных на примере создания динамического XML документа, выводящего данные из БД Family. Листинг CSP приложения приведен ниже: <script language="Cache" runat="Server"> do %response.SetHeader("content-type","txt/xml") write "" write "<xml>" set o=##Class(Family.Family).%OpenId(1) write "" write "" write "",o.Father.FIO,"" write "" write "" write "",o.Children.GetAt(1).Personal.FIO,"" write "" write "" write "" do o.%Close() Методом SetHeader системного класса %Response выставлен HTTP заголовок, который указывает браузеру, что данный документ является XML документом. Для экспорта всех свойств класса необходимо либо вывести их с помощью команды write, как показано выше, либо использовать метод XMLExport класса %XML.Adaptor. Для использования методов класса %XML.Adaptor, необходимо прописать его как супер-класс или класс-предок для всех классов, которые подлежат экспорту: Class Family.Family Extends (%Library.Persistent,%XML.Adaptor) Далее, необходимо создать следующую CSP страницу: <script language="Cache" runat="Server"> d %response.SetHeader("content-type","txt/xml") w "" s o=##Class(Family.Family).%OpenId(1) d o.XMLExport() d o.%Close() Также в Caché поддерживается стандарт MS XML-SQL Server, реализованный функциональностью класса %CSP.XMLSQL. За дополнительной информацией обращайтесь к документации класса. Импорт данных. Существует два способа импорта данных из документа XML в объекты БД: 1. Импорт данных непосредственно в классы Caché. В этом случае структура XML документа должна соответствовать структуре
30
класса Caché, т.е. имена XML тэгов должны соответствовать именам свойств класса. 2. Использование COS-интерфейса к SAX парсеру для ручного заполнения структур данных Caché данными из XML документов. Рассмотрим оба способа импорта на примерах: 1. Для импорта данных непосредственно в класс Caché необходимо воспользоваться методами системного класса %XML.Reader. Импорт осуществляется в несколько этапов. На первом этапе проводится проверка XML документа на удовлетворение структурным правилам XML. Далее создается экземпляр класса в памяти и соответствующим свойствам класса присваиваются значения XML элементов. Пользователю возвращается OREF созданного экземпляра. Для непосредственной записи экземпляра в БД необходимо вызвать соответствующие методы класса (%Save(), если класс наследует свое поведение от %Persistent). Далее процесс повторяется пока не достигнут закрывающий корневой тэг. Пример: Set reader = ##class(%XML.Reader).%New() do reader.Correlate(xmlElem,OclassName) set ex=reader.Start(fileName) While (reader.Next(.object)) { set ex=object.%Save() } Correlate() – установить отношение между XML тегом и классом Caché. Start() – начать парсинг XML документа. Next() –обработать следующий тэг. 2. SAX парсер – это событийный парсер. Происходит последовательное сканирование XML документа и при обнаружении структурного элемента XML(открывающий тег, закрывающий тег, инструкция обработки, корневой тег и т.д.) создается соответствующие событие, которое обрабатывается методом пользователя. Системный класс %XML.SAX.ContentHandler предоставляет методы всех возможных событий SAX парсера. Наследуя свой класс от XML.SAX.ContentHandler и переопределяя методы событий можно определить собственный способ обработки событий и сохранения данных из XML документов в структуры данных Caché. Пример такого класса:
Class User.MyParser Extends (%Persistent, %XML.SAX.ContentHandler) { Method characters(chars As %Library.String, length As %Library.Integer) { w !,"Символы - ", chars Quit } Method endElement(uri As %Library.String, localname As %Library.String, qname As %Library.String) { w !,"Element with name "_localname_" finished" Quit } Method startElement(uri As %Library.String, localname As %Library.String, qname As %Library.String, attrs As %Library.List) { w !,"Element with name "_localname_" started" Quit 31 } }
Использование отладчика программ. Одним из новшеств Caché 5. является наличие развитого отладчика программ, встроенного в Caché Studio. С помощью отладчика программ можно локализовать ошибку путем анализа состояния данных во время пошагового выполнения кода программы. Отладке подлежат INT-программы, т.е. программы, которые не содержат макровызовов. Как было сказано выше, методы класса при компиляции преобразуются в INT-код, поэтому отладку можно применять и к методам класса. Кроме этого существует возможность отладки CSP страницы. Функции, предоставляемые отладчиком Caché, аналогичны функциям, предоставляемым другими средами разработки, таким как Borland Delphi, MS Visual Studio и др. Отладчик Caché предоставляет следующие функциональные возможности: обозначение точек останова (breakpoints), возможность отладки вызываемых из кода программ (Step Into), а также выхода из вызываемых программ (Step Out) и др. Рассмотрим работу отладчика программ на примере отладки следующей Caché программы: Divide() N Div W !,”Введите делитель и делимое, разделенные запятыми: ” R Div If $Length(Div,”,”)’=1 w !,”Неправильно введены данные” quit 0 If $Piece(Div,”,”,1)=0 w !,”Делитель не может быть равным 0” quit 0 W “Результат деления = ”,$Piece(Div,”,”,2)/ $Piece(Div,”,”,1) Q1 Сохраняем программу под именем Divide и компилируем. Далее необходимо определить имя Caché программы, подлежащей отладке. Для этого необходимо вызвать настройки проекта путем выбора пункта меню Project->Settings . Затем на вкладыше Debugging Target в поле Caché Routine указать имя программы (^Divide()). Точку останова (breakpoint) можно выставить либо путем нажатия клавиши F9, либо выбором пункта меню Debug->Breakpoints->Toggle Breakpoint. Снять точку останова можно повторным нажатием на клавишу F9. Для просмотра установленных точек останова необходимо выбрать пункт меню Debug->Breakpoints->View Breakpoints. Для запуска отладчика необходимо нажать клавишу F5 или выбрать пункт меню Debug->Start. Для остановки отладчика необходимо нажать на комбинацию клавиш Shift-F5 либо выбрать пункт меню Debug->Stop. Во время отладки можно просматривать текущее состояние как локальных переменных, так и глобальных. Для этого необходимо выставить watch на переменную, путем указания имени переменной в окне Watch. Администрирование Caché. В стандартной поставке системы разработчику предлагается два средства администрирования Caché:
32
• •
Configuration Manager Control Panel. С помощью Configuration Manager можно выполнить следующие функции администрирования: • Создать новую БД, удалить или изменить настройки существующей БД. С точки зрения физического хранения, БД Caché – это бинарный файл CACHE.DAT. Для каждой БД создается свой файл CACHE.DAT в отдельной директории. • Определить область (Namespace) для существующей БД, под которой в Caché понимается логическая карта, на которой указаны имена многомерных массивов - глобалей и программ файла CACHE.DAT, включая имена каталога-директории и сервера данных для этого файла. При обращении к глобалям используется имя области. • Определить CSP-приложение. Для использования CSP-приложений необходимо определить виртуальную директорию на web-сервере, физическую директорию хранения CSP-приложений, а также несколько специфических для CSP настроек, таких как, к примеру, класс-предок для CSP приложений (по умолчанию принимается системный класс %CSP.Page). • Определить сетевое окружение Caché. В Caché реализован собственный протокол работы с сетью распределенного окружения БД, носящий название DCP (Distributed Cache Protocol). С помощью интерфейсов Configuration Manager можно определить источники данных в сети, а также определить связи между различными компонентами сети. • Настройка системы Caché. Разработчику предоставляется возможность конфигурирования различных компонент Caché, таких как параметры журналирования, настройки теневых серверов, параметры сервера лицензий, параметры Caché-процессов и другие. Утилита Control Panel предоставляет схожий набор функций администрирования и добавляет следующие новые: • Управление процессами Caché. • Настройка параметров защиты глобалей, таких как разрешение на редактирование/создание/чтение глобалей различными группами пользователей. • Определение пользователей системы с присваиванием им имени пользователя, пароля и определение параметров доступа. • Просмотр файлов журнала. Журналирование в Caché выполняется на уровне глобалей. • Определение теневых серверов системы. • Создание резервных копий баз данных.
33
Рис.8.Configuration manager. Рассмотрим создание базы данных, а также соответствующей области с помощью мастеров, включенных в Configuration manager. Для работы с данными из БД, каждой создаваемой базе данных должна соответствовать область, имеющая, как и база данных уникальное имя. Для создания области необходимо перейти во вкладку Namespaces и нажать кнопку Add для вызова мастера области. На первом шаге мастера области необходимо указать имя создаваемой области, а также выставить флажок, для автоматического создания виртуальной директории CSP-приложений. Вводим название области FAMILY и разрешаем создание виртуальной директории. Доступ к одной и той же базе данных можно получить через разные области. Следующий шаг мастера областей служит для определения базы данных. Создадим новую БД для этого необходимо нажать на кнопку Define a New Database для вызова мастера баз данных. Первый шаг мастера баз данных служит для определения имени базы данных, а также флажка для определения месторасположения БД (локальная или удаленная). Вводим имя БД FAMILY и не выставляем флажок. На следующем шаге определяется физическая директория местонахождения файлов БД. Вводим имя директории c:\cachesys\family. Если директория не существует, она будет создана автоматически. На следующем шаге необходимо определить размер блока БД, а также начальный размер БД (далее он будет увеличиваться автоматически). Во всех создаваемых проектах рекомендуется использовать блок размером 8кб. Выбираем 8кб и завершаем работу мастера баз данных кнопкой Finish. Завершаем работу мастера областей нажатием кнопки Finish.
34
Иконка для созданной области и базы данных серого цвета, это означает, что БД и область не инициализированы. Для инициализации и начала работы с созданной БД необходимо закрыть Configuration manager и если требуется перезагрузить Caché. Рассмотрим параметры созданных базы данных, области и CSP приложения. Каждая область содержит следующие параметры: 1. Default database. Параметры базы данных. 1.1.Globals, System Globals. Определение базы данных –источника глобалов для области. 1.2. Routines, System Routines. Определение базы данных –источника программ Caché для области. 1.3. Caché Library . Определение базы данных –библиотеки системных классов и программ Caché. 1.4. Temporary Storage. Определение базы данных для хранения временных данных Caché. 2. Global Mapping. Отображение глобалей из других БД. 3. Routine Mapping. Отображение программ Caché из других БД. База данных имеет следующие параметры, выставить которые можно вызвав окно Caché Database Edit: • Read Only. БД только для чтения. • Mount Required on Startup. Монтирование БД при запуске. Рассмотрим параметры CSP приложения : • Namespace. Область, определяющая БД, где хранятся классы CSP. • Caché Physical Path. Физический путь к CSP документам. По умолчанию это директория к папке /cachesys/CSP/Namespace. • Recurse. Разрешение на использование файлов из вложенных папок. • Auto Compile. Автоматическая компиляция документов CSP в классы Caché, если дата изменения документа CSP отличается от даты компиляции класса Caché. • Event Class. Класс, методы которого будут вызваны при появлении CSP событий, таких как TimeOut. • Default Timeout. Количество секунд времени простоя сессии. • Default Super Class. Класс-предок для CSP приложений, по умолчанию %CSP.Page. • Use Cookies for session. Параметр позволяющий запретить или разрешить использование cookies. Если запрещено, то через URL посылается зашифрованная строка символов CSPCHD, уникально идентифицирующая сессию. • Serve files. Параметр, разрешающий встроенному web-серверу обслуживать внешние файлы, находящиеся в той же директории такие как html и jpg. • Default Page. Страница, которая будет вызвана при обращению к URL. • Custom Error Page. CSP или CLS страница, которая будет вызвана в случае ошибки генерации страницы. • Package name. Имя пакета, в котором будут создаваться классы CSP приложений. • Use Per Request Licensing. Использовать лицензирование по запросу, а не сессионное.
35
Заключение. В учебном курсе описана лишь малая часть того, что реализовано в Caché. Кроме описанных интерфейсов, Caché предоставляет ODBC- и JDBC-драйверы для представления данных из СУБД Caché в виде реляционных таблиц и работы с ними. СУБД Caché предоставляет стандартные ActiveX-компоненты, которыми можно воспользоваться при создании пользовательского приложения в среде Visual Basic. Кроме этого, предоставляется мастер создания форм Caché Form Wizard для облегчения разработки пользовательских форм в среде Visual Basic. В Caché реализованы интерфейсы CALLIN/CALLOUT, предназначенные для прямого вызова функций СУБД Caché из С-программ и вызова функций операционной системы из Caché, Также предоставляется интерфейс для работы с функциями DLL- библиотек. Caché предоставляет модуль интеграции со средой проектирования информационных систем Rational Rose. При этом UML-диаграмму классов можно экспортировать напрямую в БД Caché, причем классы, а также типы данных свойств на диаграмме будут полностью соответствовать созданным классам и свойствам классов Caché. Разработчику предоставляется также возможность создания описаний классов Caché на языках Java или С++ и дальнейшей работы с методами и свойствами классов Caché так, как если бы эти классы были реализованы на Java или С++. За дополнительной информацией обращайтесь к следующим источникам: 1. Документация, поставляемая с Caché. 2. СУБД Caché Объектно-ориентированная разработка приложений. Учебный курс. В.Кирстен и др. СПб: Питер, 2001г. 3. Постреляционная технология Caché для реализации объектных приложений. Н.Е. Кречетов и др. М: МИФИ, 2001г. 4. Материалы сайта www.intersystems.ru . 5. [email protected].
36
Приложение 1.
Мастер классов - Шаг1. Общие сведения о классе.
Мастер классов – Шаг 2.Вид класса.
37
Мастер классов – Шаг 3. Выбор дополнительных возможностей класса.
Мастер свойств – Шаг 1. Общие сведения о свойстве.
38
Мастер свойств – Шаг 2. Определение вида свойства.
Мастер свойств – Шаг 3. Характеристики свойства.
39
Мастер свойств – Шаг 4. Параметры свойства.
Мастер методов- Шаг 1. Общие сведения о методе
40
Мастер методов – Шаг 2. Сигнатура метода
Мастер методов – Шаг 3. Характеристики метода.
41
Мастер методов – Шаг 4. Код метода.
42