Интерпретация этого принципа для баз данных состоит в том, что объект инкапсулирует и программу и данные.
Рассмотрим, например, объект Служащий. В реляционной системе служащий представляется кортежем. Запрос к нему осуществляется с помощью реляционного языка, а прикладной программист пишет программы для изменения этой записи, например повышение зарплаты служащего или прием на работу. Такие программы обычно пишутся либо на императивном языке программирования с включением в него операторов языка манипулирования данными или на языке четвертого поколения и хранятся в обычной файловой системе, а не в базе данных. Таким образом, при таком подходе имеются кардинальные различия между программой и данными, а также между языком запросов (для незапланированных запросов) и языком программирования (для прикладных программ).
В объектно-ориентированной системе служащий определяется как объект, который состоит из части данных (очень даже вероятно, что эта часть практически совпадает с записью, определенной для реляционной системы) и части операций (эта часть состоит из операций повышения зарплаты и приема на работу и других операций для доступа к данным сотрудника). При хранении набора сотрудников, как данные, так и операции хранятся в базе данных. Таким образом, имеется единая модель данных и операций, и информация может быть скрыта. Никакие иные операции, кроме указанных в интерфейсе, не выполняются. Это ограничение справедливо как для операций изменения, так и для операций выборки.
Инкапсуляция обеспечивает что-то вроде “логической независимости данных”: мы можем изменить реализацию типа, не меняя каких-либо программ, использующих этот тип. Таким образом, прикладные программы защищены от реализационных изменений на нижних слоях системы.
Здесь уместно вспомнить о “проблеме 2000 года”, возникшей из-за того, что в СУБД отводилось всего два разряда на год даты. Чтобы исправить возникающую ошибку, нужно пересмотреть заново весь код приложения! В ООБД для решения аналогичной проблемы требуется исправление небольшого количества методов, работающих с данными даты.
Объекты в БД обладают индивидуальностью. Даже при изменении структуры и поведения объекта, его индивидуальность сохраняется. Два объекта в системе отличаются своими идентификаторами. Идентификатор является характеристикой индивидуальности. Понятие индивидуальности ново для реляционных баз данных. В чисто реляционной БД все кортежи в пределах одной таблицы отличаются между собой. Характеристика различия – первичный ключ. Многие современные реляционные базы данных допускают существование в пределах одной таблицы одинаковых кортежей. И потребность в этом есть, иначе не было бы квалификатора DISTINCT в операторе SQL SELECT.
Идентификатор объекта в БД позволяет различить между собой два одинаковых по значению объекта. Фактически, он играет роль дескриптора адреса объекта. Таким образом, пользователь работает с объектом не через его адрес, а через его идентификатор.
В современных ООБД для ускорения доступа к объектам идентификаторы наделяются составной структурой.
Имеются два основных подхода для идентификации объектов:
· Составной адрес (Structured address)
· Заменитель (Surrogate)
Составной адрес состоит из физической части (сегмента и номера страницы) и логической части (внутристраничный индекс), которые являются масками фиксированной длины и, соединяясь, дают идентификатор. Составные адреса более популярны в современных ООБД как более эффективные: за один дисковый доступ можно получить адрес объекта. Использование составного адреса как идентификаторов приводит к зависимости от организации физического хранения. Это приводит к трудностям при перемещении данных для хранения на другое устройство.
Заменитель – чисто логический идентификатор, генерируемый по некоторому алгоритму, который гарантирует уникальность. В заменителях, индекс (также называется директорией объекта), часто используется для отображения идентификаторов в расположение объектов. Эффективность операций с базой данных во многом определяется скоростью доступа к одиночному объекту. Часто объекты связаны между собой и доступ к одному объекту происходит через доступ к другому. Например, через объект-список происходит доступ к его элементам. Во многих случаях создание объекта (например, глубоким копированием) приводит к каскадному созданию других объектов, составляющих его содержимое. Использование кластеризации помогает организации быстрого доступа к группе связанных объектов. Кроме того, размещение объектов в одной области дискового пространства также увеличивает быстродействие.
В работе [16] описан подход к построению идентификаторов-заменителей. Идентификатор состоит из двух частей: кода кластера и номера в последовательности. Такой подход основывается на следующих трех принципах:
1) Идентификатор объекта должен содержать информацию о кластере, который группирует совместно используемые объекты
2) Должны быть допустимы произвольные размеры кластеров
3) Идентификаторы объектов должны подчиняться достаточно однообразному представлению, чтобы они могли выступать в качестве псевдоключей динамического хеширования.
Есть три признака, по которым СУБД могут принимать решение о месте размещения объектов:
1) Правила, заданные в схеме БД
2) Указание пользователя
3) Статистика доступа
В дипломной работе, несмотря на заманчивость идеи кластеризации, принят тривиальный подход: идентификатор нового объекта – это значение максимального идентификатора, использующийся в системе, плюс один. Объекты также хранятся не в виде кластеров и не вкладываются друг в друга. Хотя система управления памятью позволяет организовать и такой способ хранения.
В ООБД при сравнении двух объектов между собой различают идентичность и эквивалентность объектов.
Определение идентичности
Два объекта являются идентичными, если их идентификаторы совпадают. Поскольку в системе не может быть двух объектов с одинаковыми идентификаторами, это означает, что это один и тот же объект, на который ссылаются с двух разных мест. Идентичность обозначается так: o1º o2.
Определение N-эквивалентности
Пусть 0-эквивалентность (обозначается »0) то же самое, что проверка идентичности º. Тогда для любых двух объектов o1, o2ÎO, o1и o2 n-эквивалентны (обозначается o1 »n o2) для n > 0, если:
Существует атомарный объект c, такой, что значение(o1) = значение(o2) и их поведения идентичны;
Существует объект-агрегат c, такой, что FID каждого поля с присутствует в o1и o2, а также верно обратное: FID каждого поля o1 (o2) присутствует в c,
значение(o1)=[A1 : x1, …, Am : xm] и значение(o2)=[A1 : y1, …, Am : ym], и при этом
xi »n-1yiдля 1£ i £ n; или
Существует объект-условие c, такой, что значение(o1) = <x1, x2, x3> и значение(o2) = <y1, y2, y3> и xi »n-1yiдля 1£ i £ 3; или
Существует объект-множество c, такой, что значение(o1) = {x1, …, xl} и значение(o2)
= {y1, …, ym} и l = mи для каждого xi(yj) существует один yj(xi) : xi »n-1yjдля 1£ i,j £l; или
Существует объект-список c, такой, что значение(o1) = (x1, …, xl) и значение(o2) = (y1, …, ym) и l = mи xi »n-1yiдля 1£ i £l.
Два объекта называются эквивалентными (o1 » o2) тогда и только тогда, когда
o1 »n o2 для некоторого n > 0.
Введение идентификатора поля позволяет преодолеть трудность определения размещения данных полей агрегатов. Суть проблемы заключается в том, что если мы наследуем классы B и C от класса A, а затем наследуем множественно класс D от классов B и C, то экземпляр класса D одновременно является экземпляром классов A, B и C. При этом важно, чтобы "старый" класс (например, A) умел работать с объектами класса D. Эта проблема рассматривается в работе [10], в которой авторы вводят следующие ограничения целостности структуры объектов:
1. В БД не могут существовать отдельные собственные части подклассов
2. Каждой части сложного объекта должна соответствовать только одна собственная часть.
В качестве решения они предлагают использование ссылок на классы и каждую собственную часть класса хранить отдельно.
В дипломной работе предлагается вместо хранения ссылок на классы установить для каждого поля свой идентификатор. При наследовании поле сохраняет свой идентификатор. Таким образом, переименование полей не нарушает связь наследования. Переименование может быть автоматическим, например, из-за конфликтов имен полей при множественном наследовании. Аналогично поступает оператор SQL Select, когда в качестве результата запроса ему нужно вернуть несколько столбцов, имеющих одинаковые имена.
Идентификаторы полей уникальны в пределах базы данных, т.е. при объявлении нового поля в классе, идентификатор поля в дальнейшем появляется только в классах-наследниках и только через наследование.
Кроме того, программисты могут использовать для имен полей привычный для них родной язык, другими словами: есть возможность создавать синонимы имен полей.