Полиморфная структура базы данных ORM - PullRequest
1 голос
/ 21 марта 2011

Я помню, когда - давным-давно - я возился с Java ActiveObjects ORM, я столкнулся с шаблоном базы данных, который, как он утверждал, поддерживал.

Однако очень трудно найти имя шаблонав поисках общей идеи, поэтому я был бы очень признателен, если бы кто-то мог дать мне название этого шаблона и некоторые мысли о «чистоте» его использования.


Шаблон был определенкак таковой:

Table:
  reference_type <enum>
  reference      <integer>
  ...

... где значение поля reference_type будет определять тип (и, следовательно, таблицу), на который ссылается.Таким образом:

User:
  location_type <l&l, address, city, country>
  location      <integer>
  ...

... где, в зависимости от значения поля location_type, внешний ключ location будет ссылаться на l&l, address, city или country таблица.

Ответы [ 2 ]

2 голосов
/ 21 марта 2011

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

Держитесь подальше от таких шаблонов.В то время как ORM упрощает сопоставление таблиц базы данных с типами, таблицы не являются типами, и наоборот .Хотя неясно, что должна делать описанная вами модель, у вас не должно быть столбцов, которые служат поддельными внешними ключами для нескольких таблиц (когда я говорю «поддельные», я имею в виду, что вы храните значение простого идентификатора, котороесоответствует первичному ключу другой таблицы, но вы не можете определить столбец как внешний ключ).

Моделируйте вашу базу данных для представления данных, моделируйте ваши объекты для представления процесса и используйте ORM и промежуточные слои для выполнения перевода;не пытайтесь вставить базу данных в свой код и не вставляйте свой код в базу данных.

Редактируйте в ответ на комментарий

Вы смешиваете терминологию базы данных и OO;хотя я не знаком с синтаксисом, который вы используете для определения этой функции, я предполагаю, что это функция экземпляра типа User с именем getLocation, которая не принимает параметров и возвращает объект Location.Базы данных не поддерживают понятия функций экземпляра (или любых основанных на типах);Реляционные базы данных могут иметь пользовательские функции, но это простые процедурные функции, которые принимают параметры и возвращают либо значения, либо наборы результатов.Они никоим образом не соответствуют конкретным таблицам или полям, за исключением того факта, что вы можете использовать их в теле функции.

При этом здесь есть два вопроса, на которые нужно ответить: как это сделатьчто вы спросили, и что может быть лучшим решением.

Для того, что вы спросили, похоже, что у вас есть отношение супертип-подтип, которое является стандартным дизайном базы данных.шаблон.В этом случае у вас есть одна таблица супертипа, которая представляет родительский элемент:

Location
---------------
LocationID (PK)
...other common attributes

(обратите внимание, здесь я использую LocationID для простоты; у вас должны быть более конкретные и логические атрибуты дляопределить первичный ключ, если это возможно)

Тогда у вас есть одна или несколько таблиц, которые определяют подтипы:

Address
-----------
LocationID (PK, FK to Location)
...address-specific attributes

Country
-----------
LocationID (PK, FK to Location)
...country-specific attributes

Если конкретный экземпляр Location может быть только одним из подтипов,затем вы должны добавить значение дискриминатора в родительскую таблицу (Location), которое указывает, какому из подтипов оно соответствует.Вы можете использовать ограничения CHECK, чтобы в этом поле находились только допустимые значения для данной строки.

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

  • Координаты на основе координат (L & L)
  • Муниципальные / Почтовые / Etc. Местоположения (Страна, City, Address), и каждый из них является просто более конкретной версией предыдущего

. Учитывая это, простая модель будет выглядеть следующим образом:

Location
------------
LocationID (PK)
LocationType (non-nullable) ('C' for coordinate, 'P' for postal)

LocationCoordinate
------------------
LocationID (PK; FK to Location)
Latitude (non-nullable)
Longitude (non-nullable)

LocationPostal
------------------
LocationID (PK, FK to Location)
Country (non-nullable)
City (nullable)
Address (nullable)

ТеперьЕдинственная проблема, которая остается, состоит в том, что у нас есть обнуляемые столбцы.Если вы хотите, чтобы ваши запросы были простыми, но не обращали внимания (оправданно!) На то, что люди оставляют пустые столбцы, вы можете оставить все как есть.Если вы хотите перейти к тому, что большинство людей сочли бы базой данных с лучшим дизайном, вы можете перейти к 6NF для наших двух обнуляемых столбцов.Выполнение этого также будет иметь приятный побочный эффект, так как даст нам немного больше контроля над тем, как эти поля заполняются, без необходимости делать что-либо дополнительное.

Наши два поля, которые можно обнулять, это City и Address.Я собираюсь предположить, что наличие Address без City было бы бессмыслицей.В этом случае мы удаляем эти два атрибута из таблицы LocationPostal и создаем еще две таблицы:

LocationPostalCity
------------------
LocationID (PK; FK to LocationPostal)
City (non-nullable)

LocationPostalCityAddress
-------------------------
LocationID (PK; FK to LocationPostalCity)
Address (non-nullable)
0 голосов
/ 21 марта 2011

Мне кажется, что город и страна будут частью таблицы address, и что L & L не будет взаимоисключающим с адресом (у вас может быть и то и другое ...), так что зачем себя так ограничивать одним или другой?

Более того, это не позволит столбцу location обеспечить ссылочную целостность, не так ли, поскольку он не всегда ссылается на одну и ту же таблицу?

...