Byte/RE ИТ-издание

Разработка приложений для СУБД Caché

Официальная дата выхода СУБД Caché компании InterSystems (http://www.intersystems.com) — 1997 г. Однако ее история восходит к началу 70-х и связана с легендарными компьютерами PDP компании DEC. Изначально СУБД Caché создавалась как универсальная система программирования для Массачусетского госпиталя. Технология оказалась удачной и постепенно стала проникать и в другие отрасли; сейчас Caché активно используется в промышленности, финансах, торговле и т. д.

Принципиальное отличие Caché от других СУБД состоит в том, что в ней поддерживается принцип единой архитектуры данных. Это означает, что фактически для обращения к одним и тем же данным можно использовать как реляционное, табличное представление (например, при построении отчетов), так и объектное (к примеру, при разработке приложения в объектно-ориентированной среде), а в случае необходимости можно обеспечить высокую производительность, используя прямой доступ к многомерным массивам данных (иерархическим глобалам).

Основное средство разработки в этой системе — интегрированная с СУБД GUI-среда Caché Studio. В ней можно создавать различные классы объектов путем описания их определений, включая свойства и методы. Эти определения задаются с помощью форм и меню (встроенных мастеров) или напрямую на языке описания объектов. В дополнение к этому Caché Studio можно использовать для создания программ на встроенных языках Caché Object Script и Caché Basic, а также CSP-страниц (Caché Server Pages — технология создания Web-интерфейса для приложений Caché).

Объектная модель построена на основе стандарта ODMG (Object Data Management Group). При создании, сохранении и манипулировании экземплярами объектов Caché поддерживает основные концепции современной объектной технологии с инкапсуляцией, полиморфизмом и наследованием. В объектной модели Caché реализовано также множественное наследование, при котором класс порождается сразу несколькими родительскими классами.

Наибольший интерес для нас представляют хранимые классы, которые наследуются от системного класса %Persistent. Объекты этого класса и размещаются в базе данных. В Caché поддерживается несколько способов хранения объектов:

  • автоматическое хранение в многомерной базе данных Caché;
  • хранение в любых структурах, определенных пользователем;
  • хранение во внешних таблицах реляционных баз данных, доступных через шлюз Caché Gateway.

Для доступа к объектам можно использовать уникальные идентификаторы объектов, а также SQL-запросы, причем значением атрибута могут быть как простые типы данных, так и экземпляры встраиваемых классов:

SELECT Company->Name FROM Sample.Employee
ORDER BY Company->Name

Встраиваемые классы наследуются от класса %SerialObject. Их экземпляры существуют в памяти как независимые объекты, однако сохраняются в базе данных, лишь будучи встроенными в другие объекты. Кроме того, свойствами объектов могут быть ссылки на объекты, потоки данных, различные виды коллекций, многомерные переменные и двунаправленные связи между хранимыми объектами.

Внешние интерфейсы Caché

Команда программистов будет работать более продуктивно, имея дело со знакомой средой разработки. Предоставляя объектный доступ и SQL, Caché поддерживает интерфейсы для большинства распространенных средств разработки. Это позволяет выбрать ту модель данных, которая наилучшим образом соответствует требованиям задачи и условиям, в которых ведется разработка.

В Caché существует широкий спектр интерфейсов, отвечающих за быстрый доступ к объектам Caché из разнообразных сред, включая Java, C++, COM, .NET, EJB, Perl, Python и Delphi. Компоненты Caché отвечают за весь сетевой обмен между клиентом и сервером приложений. Caché обеспечивает двустороннее взаимодействие по протоколу SOAP и поддерживает XML-обмен. Рассмотрим эти способы подробнее.

Доступ через ODBC. Этот внешний реляционный доступ обеспечивается сервером Caché. Вместе с Caché поставляется ODBC-драйвер (InterSystems ODBC), который позволяет внешним приложениям выполнять SQL-запросы к данным Caché как к реляционным таблицам. Этот вид доступа подходит, например, для получения данных для генераторов отчетов, аналитических пакетов и других реляционных приложений. Использование реляционного доступа к Caché по протоколу ODBC мало чем отличается от использования ODBC для других СУБД — за исключением, пожалуй, возможности добиться выигрыша по скорости.

Объектное взаимодействие с Java. Язык программирования Java весьма популярен, но связь написанных на нем приложений с большинством баз данных — непростая задача. Подключение к реляционной базе данных требует отображения объектного представления в плоские таблицы. Написание большого объема кода на SQL занимает очень много времени и лишает преимуществ объектную технологию Java. Возможность работать с объектами Caché напрямую избавляет разработчика от забот, связанных с предоставлением описания данных для хранения, а использовать объекты для работы с базой данных гораздо проще и предпочтительней. Java-приложение может взаимодействовать с Caché следующими способами:

  • для любого класса Caché можно создать его проекцию как класс Java, так что свойства и методы этого класса будут доступны, как если бы это был объект Java;
  • классы Caché можно проецировать как Enterprise Java Beans;
  • высокопроизводительный доступ для SQL полностью обеспечивается “родным” драйвером JDBC на Java, по аналогии с другими СУБД;
  • технология InterSystems Jalapeno создает классы Caché из описаний классов POJO.

Объектный доступ через проекции классов. Для каждого класса Caché можно создать соответствующую проекцию — класс Java (или EJB) с методами, соответствующими каждому свойству и методу класса Caché. Для программ на Java эти классы ничем не отличаются от других классов Java-приложения. Сгенерированные классы Java используют библиотеку Java из поставки InterSystems для связи клиента с сервером.

Сервер приложений Caché хранит состояние каждого объекта Caché, в то время как свойства класса также кэшируются клиентом для обеспечения оптимальной производительности. Вызовы методов Java вызывают соответствующие методы на сервере приложений Caché, включая методы сохранения и открытия объекта. Для клиента эти процессы полностью прозрачны — для него не играет роли, с каким сервером данных Caché происходит обмен данными, даже если сервер приложений Caché работает с реляционной базой данных.

Методы Caché, написанные на Java. Методы классов Caché могут быть написаны на Java в интегрированной среде разработки Caché Studio. Но, в отличие от Caché ObjectScript и Basic, методы Java не выполняются на сервере Caché — вместо этого они включаются в генерируемый класс Java и выполняются на любой виртуальной машине Java.

Предоставление механизма хранения для приложений J2EE. Разработчики приложений J2EE, использующие EJB (Enterprise Java Beans), работают с объектами в основном до момента доступа к базе данных; после этого они должны использовать SQL. Caché может предоставить для таких приложений быстрый SQL-доступ через интерфейс JDBC. В то же время доступ с использованием SQL далеко не всегда оказывается предпочтительным.

Объектные базы данных представляют более естественную технику доступа для программистов EJB. Caché проецирует классы Caché как EJB, автоматически генерируя высокопроизводительные методы хранения для BMP (Bean-Managed Persistence). Это позволяет обойтись без лишнего кодирования при использовании SQL и объектно-реляционного отображения.

Описание классов Java в Jalapeno. Вместо описания классов в Caché и создания их проекции как компонента Java технология InterSystems Jalapeno предлагает другой подход, который позволяет разработчикам на Java описывать классы в привычной среде разработки Java и автоматически создавать описания для хранения этих классов в Caché. При этом классы, разработанные в Java, остаются без изменений, а Caché предоставляет библиотеку с API, обеспечивая механизм хранения и запросов по этим классам.

Caché и .NET

На сегодняшний день широко распространена разработка приложений на платформе .NET. Благодаря открытому и гибкому механизму доступа к данным Caché предоставляет различные интерфейсы к .NET — SQL, объектный, SOAP — и обеспечивает целостное взаимодействие с платформой .NET Framework. Разработчик может выбирать наиболее подходящую для себя технологию — с любой из них будет достигнута высокая производительность и масштабируемость Caché.

Основной механизм, предоставляющий доступ к Caché из .NET-приложений, — это Caché Managed Provider для .NET. Особенность этого механизма заключается в том, что он, используя единый интерфейс, поддерживает реляционный и объектный доступ, не требуя создания проекции объектов на таблицы. Caché Managed Provider обеспечивает реляционный доступ к данным, используя API ADO.NET, а также высокопроизводительный и удобный объектный доступ к данным через автоматически генерируемые промежуточные классы. Эти промежуточные классы соответствуют классам Caché и обеспечивают хранение объектов, извлечение и кэширование данных, управление жизненным циклом объектов. За счет того, что Caché Managed Provider реализован как управляемый .NET-код, достигается простота развертывания в среде .NET. И наконец, Caché Managed Provider для .NET можно использовать в многопоточных (multi-threaded) .NET-приложениях, так как он безопасен для многопоточных процессов.

Для работы Caché Managed Provider используется системная библиотека InterSystems.Data.CacheClient.dll, которая содержит два пространства имен: Intersystems.Data.CacheClient и Intersystems.Data.CacheTypes.

Первое из них, Intersystems.Data.CacheClient, представляет собой стандартизованный интерфейс ADO.NET, который содержит классы, полностью соответствующие аналогичным классам других провайдеров, таких, как Microsoft System.Data.OleDb или System.Data.SqlClient. В рамках Caché Managed Provider реализованы CacheClient-версии стандартных ADO-классов (например, CacheCommand, CacheConnection, CacheDataAdapter и CacheDataReader). Они применяются точно так же, как аналогичные классы для работы с другими базами данных, поэтому разработчик, используя привычные для него ADO-команды, может получать доступ к данным Caché и обрабатывать их, не обладая никакими специальными знаниями о синтаксисе и командах Caché.

Второе пространство имен, Intersystems.Data.CacheTypes, включает в себя специальные средства для работы с объектами Caché. Классы CacheTypes позволяют работать с объектами .NET, которые представляют собой точные аналоги объектов Caché, и могут использоваться так же, как они используются во встроенных языках Caché — ObjectScript или Caché Basic. В отличие от стандартного ADO-интерфейса прокси-объекты Caché обеспечивают прямое управление объектами и структурами данных Caché.

Таким образом, Caché Managed Provider — это компонент, который обеспечивает одновременно и реляционный, и объектный доступ к данным, используя общий программный интерфейс.

Реляционный доступ к данным

Caché Managed Provider предоставляет стандартный набор классов, таких, как Connection, Command, DataAdapter и т. п. для взаимодействия с Caché (рис. 1). Ниже приведены краткие описания некоторых классов и примеры их использования.

Рис. 1. Схема доступа к данным Caché из ADO.NET.

CacheConnection — этот класс предназначен для соединения с источником данных (т. е. Caché) и содержит свойства, необходимые для подключения. Пример установления соединения:

String cacheConnectString = “Server =
<p>localhost; Log File=c:\cprovider.log;
<p>Port=1972; Namespace=Samples; Password =
<p>SYS; User ID = _SYSTEM;”;
<p>cnCache = new CacheConnection(cacheConnectString);
<p>cnCache.Open();
<p>…

CacheDataAdapter — этот класс включает в себя набор команд, а также соединения с источником данных, которые используются для получения данных из источника и помещения их в объект .NET типа System.Data.DataSet. Может также использоваться для обновления данных источника. Пример заполнения DataSet:

dsCache= new DataSet();
<p>daCache= new CacheDataAdapter();
<p>daCache.SelectCommand= new CacheCommand
<p>(“Select ID, Name, DOB from Sample.Person”,
<p>cnCache, txCache);
<p>daCache.Fill(dsCache, “Sample_Person”);

CacheCommand — класс, представляющий собой команды SQL или хранимые процедуры, которые необходимо выполнить. Пример обновления данных в БД через запрос с параметром (CacheParameter):

spCache = new CacheCommand(“Update
<p>Sample.Person Set Name = ?
<p>where ID = ?”, cnCache, txCache);
<p>CacheParameter pName = new CacheParameter();
<p>pName.ParameterName= “Name”;
<p>pName.CacheDbType= CacheDbType.NVarChar;
<p>pName.Direction = ParameterDirection.Input;
<p>pName.Value = txtName.Text;
<p>…
<p>spCache.Parameters.Add(pName);
<p>spCache.Parameters.Add(pID);
<p>spCache.ExecuteNonQuery();

Кроме описанных классов имеются и другие: как стандартные (например, CacheDataReader), так и специальные, предназначенные для удобства работы с Caché. При этом в общем случае, как видно из примеров, работа с данными на основе реляционного доступа аналогична работе средствами ADO с другими источниками данных.

Объектный доступ к данным

Одна из важнейших особенностей Caché — возможность объектного доступа к данным за счет использования Caché Managed Provider, а не представление данных в виде строк реляционных таблиц. В результате в .NET-приложении используются абсолютно те же классы, что и были описаны в Caché. Простейший пример работы с объектами Caché в .NET-приложении выглядит так:

CacheConnection CacheConnect = new
<p>CacheConnection();
<p>CacheConnect.ConnectionString = “Server =
<p>localhost; ”
<p>+ “Port = 1972; ” + “Namespace = SAMPLES; ”
<p>+ “Password = sys; ” + “User ID = _system;”;
<p>CacheConnect.Open();
<p>Sample.Person person = Sample.Person.OpenId
<p>(CacheConnect, “1”);
<p>Console.WriteLine(“TinyProxy output:

<p>+ person.Id() + “: “+ person.Name);
<p>person.Close();
<p>CacheConnect.Close();

Очевидно, что можно реализовать полностью аналогичный код, используя реляционный способ работы с данными, но также очевидно, что работа в объектной модели имеет ряд существенных преимуществ. Главные из них — простота и скорость реализации: объектный код достаточно понятен, что упрощает его модификацию и сопровождение.

Механизм Caché Managed Provider работает следующим образом (рис. 2). Сначала нужно описать необходимые классы в Caché Studio. Это могут быть классы, хранимые в базе данных Caché, или классы для описания бизнес-логики в Caché. Программа Caché Object Binding Wizard создает прокси-классы .NET на основе классов, определенных в библиотеке классов Caché. Эти классы реализованы при помощи managed code и содержат вызовы методов и ссылки на свойства объектов Caché.

Рис. 2. Организация работы .NET c Caché.

Во время выполнения .NET-приложение подключается к серверу Caché; при этом можно создавать экземпляры .NET-объектов, которые связаны с объектами на сервере Caché. Эти объекты используют точно так же, как другие объекты .NET .

Caché автоматически управляет всеми взаимодействиями и при этом поддерживает кэширование данных на стороне клиента. Таким образом, для работы приложения необходимы только сервер Caché и клиентские .NET-приложения, которые взаимодействуют с сервером через стандартный TCP/IP протокол. Для работы механизма Caché Managed Provider для .NET на сервере должна быть установлена СУБД Caché начиная с версии 5.1, на клиенте — Microsoft .NET Framework v2.0. Для разработки .NET-приложений требуется Microsoft Visual Studio 2005.

Предоставление информации через Web-сервисы

Для связи с .NET по протоколу SOAP СУБД Caché используется как сервер Web-сервисов, а на стороне .NET создается SOAP-клиент для работы с сервисом Caché. Любой метод класса Caché, хранимую процедуру или запрос можно автоматически представить как Web-сервис. Caché генерирует описание сервиса в файл WSDL и при вызове сервиса отправляет соответствующий документ XML.

Организовать работу Caché как сервера Web-сервисов несложно. Для этого используются специальные классы Caché, которые наследуются от системного класса %SOAP.WebService. Методы, которые должны будут предоставляться Web-сервисом, описываются так же, как обычные методы Caché, но для того чтобы эти методы были доступны внешним приложениям, для них следует указать ключевое слово WebMethod:

ClassMethod Test() As %String [ WebMethod ]
<p>{
<p> Quit “Test”
<p>}

После компиляции класса Web-сервис готов к использованию, и его работу можно проверить в Caché, просматривая соответствующую Web-страницу в браузере.

Чтобы использовать методы Web-сервиса Caché в .NET, нужно в проект Visual Studio.NET добавить Web-ссылку (Web reference), указав адрес WSDL-документа Web-сервиса. После этого в приложении .NET будет создан класс, соответствующий Web-сервису Caché. Создав новый экземпляр этого класса, разработчик получает доступ к его методам, которые представляют собой отображение соответствующих методов Web-сервиса Caché. Методы Web-сервиса Caché могут возвращать значения следующих типов:

  • %String — строка (при использовании строки с разделителями следует обратить внимание на ограничения XML, касающиеся передачи некоторых специальных символов);
  • %ListOfDataTypes — список значений;
  • %XML.DataSet — нетипизированный DataSet, который формируется как результат выполнения запроса.

Использование типа DataSet может выглядеть так:

ClassMethod GetByName() As %XML.DataSet
<p>[ WebMethod ] <p>{
<p> Set ds=##class(%XML.DataSet).%New
<p>(“User.Person:All”)
<p> Do ds.SetArgs()
<p> Quit dst
<p>}

Пример описания объекта пользовательского класса:

ClassMethod TestObj(pID as %Integer)
<p>As Sample.Person [ WebMethod ] <p>{
<p> Quit ##class(Sample.Person).%OpenId(pID)
<p>}

Соответствие между перечисленными выше типами значений методов Web-сервиса Caché и методов в .NET описано в таблице.

Типы значений методов Web-сервиса Caché и соответствующие им значения в .NET

Caché .NET
%String String — строка
%ListOfDataTypes String() — массив строк
%XML.DataSet DataSet
Объект пользовательского класса Object

При использовании %XML.DataSet результат запроса из Caché попадает в .NET в виде DataSet, содержащего единственную таблицу с данными.

При передаче объекта пользовательского класса в .NET разработчик получает значения всех свойств данного объекта Caché, в том числе и сложных, которые представляют собой ссылки на объекты других классов (например, person.adress.street). Таким образом, в общем случае в клиентском приложении имеется полная информация об объекте в виде некой иерархической структуры.

Такой способ передачи данных достаточно прост, но у него есть существенный недостаток: поскольку при использовании Web-сервисов не устанавливается постоянная связь с базой данных, невозможно напрямую вызвать методы, отвечающие за сохранение и удаление данных со стороны клиента. Впрочем, есть простой способ решения этой проблемы — всегда можно создать новый серверный метод Caché, который будет использовать соответствующие методы на стороне сервера Caché.

Заключение

СУБД Caché предоставляет как объектный, так и реляционный доступ к данным для разных средств разработки приложений. Для каждого приложения команды программистов могут выбрать ту модель данных и те интерфейсы, которые наиболее полно отвечают требованиям задачи и условиям разработки. Поддержка средств разработки Microsoft в Caché имеет очень давнюю историю — от использования COM-объектов и поддержки C++-binding до Caché Managed объектов для Framework 2.0.

Для работы с Caché можно использовать сразу три способа доступа к одним и тем же данным в рамках одного приложения (в том числе и «прямой» доступ к многомерным массивам данных). При этом объектный и реляционный доступ будут равноправными.

Вам также могут понравиться