
Глава 12. Объектно-реляционные типовые решения... 239
(Остерегайтесь применять в качестве ключей значения дат и времени. Они не только
являются значащими, но и могут привести к проблемам с переносимостью и согласован-
ностью. Особенно это касается дат, которые часто измеряются с точностью до различных
долей секунды. Подобный способ измерения может легко нарушить синхронизацию
данных и, как следствие, привести к проблемам идентификации.)
Используемые ключи могут быть уникальны по отношению к таблице или по отно-
шению ко всей базе данных. Значения ключа, уникального в пределах таблицы (table-unique
key), должны быть уникальны для каждой строки текущей таблицы (обязательное усло-
вие для того, чтобы поле могло стать ключевым), но могут повторяться в других таблицах.
В свою очередь, значения ключа, уникального в пределах базы данных (database-unique key),
должны быть уникальны для каждой строки каждой таблицы всей базы данных. В боль-
шинстве случаев можно обойтись и ключом, уникальным в пределах таблицы, однако
использовать ключ, уникальный в пределах базы данных, значительно проще, а кроме
того, это позволяет применять общую коллекцию объектов (Identity Map, 216). Не беспо-
койтесь: современные базы данных умеют работать с большими числами, поэтому значе-
ния ключей вряд ли закончатся. Разумеется, при желании вы можете написать простой
сценарий, который будет присваивать новым записям ключи удаленных объектов и та-
ким образом "экономить" значения ключей, хотя для запуска такого сценария вам может
понадобиться отсоединить приложение от базы данных. Впрочем, если вы используете
64-битовые ключи (что далеко не редкость), это вряд ли понадобится.
Используя ключи, уникальные в пределах таблицы, следует быть особенно осторож-
ным с наследованием. Если вы применяете наследование с таблицами для каждого кон-
кретного класса (Concrete Table Inheritance, 313) или наследование с таблицами для каждого
класса (Class Table Inheritance, 305), лучше выбирать ключи, уникальные в пределах всей
иерархии объектов. Впрочем, я буду использовать термин "уникальный в пределах таб-
лицы" даже тогда, когда формально это будет означать нечто наподобие "уникальный в
пределах графа наследования".
Размер ключа может влиять на производительность, в частности по отношению к ин-
дексам. В большинстве случаев это зависит от используемой СУБД и/или количества
строк в базе данных, однако, прежде чем принимать окончательное решение по поводу
формы ключей, рекомендую выполнить "черновую" проверку.
Представление поля идентификации в объекте
Самая простая форма поля идентификации — это поле, тип которого соответствует ти-
пу ключа базы данных. Таким образом, если вы используете простой числовой ключ, вам
вполне должно хватить поля какого-нибудь стандартного числового типа данных.
С составными ключами дело обстоит несколько сложнее. В этом случае рекомендую
создать класс ключа. Универсальный класс ключа может содержать в себе последова-
тельность объектов, являющихся элементами ключа. Поэтому ключевым методом класса
ключа (к сожалению, приходится мириться с подобной игрой слов!) должно стать выпол-
нение проверки на равенство. Кроме того, рекомендую реализовать метод, который будет
возвращать части ключа при отображении объекта на базу данных.
Если все ключи имеют одну и ту же базовую структуру, все операции по обработке
ключей можно вынести в супертип слоя (Layer Supertype, 491). Сюда можно поместить все
стандартное поведение, которое будет применяться в большинстве случаев, а обработку
исключительных случаев реализовать в конкретных производных классах.