Это непростой вопрос ... Базы данных SQL плохо умеют моделировать иерархии классов.
Вам понадобится хороший ORM.
То, что я положил в таблицу иерархии классов, сделайте так:
Сначала я убедился, что это уместно: например, размещение узлов, статей и т. Д. Для веб-CMS в одной таблице имеет смысл, потому что это все варианты одного и того же.
Идея состоит в том, что вам нужно создавать столбцы базы данных для поиска, индексации и выполнения запросов SQL, но вам не нужно хранить всю вашу информацию в столбце базы данных. Остальное можно сохранить в сериализованном объекте в столбце BLOB.
В таблице есть
- конечно, столбец, который указывает, к какому классу относится данная строка
- несколько «основных» столбцов, которые являются общими для всех классов, в основном для полей базовых классов.
- другие столбцы, которые используются только некоторыми подклассами, но которые мне нужны для поиска, поэтому они должны быть проиндексированы
- BLOB-объект, содержащий все остальные данные объекта.
Обычно, когда я сохраняю объект в базе данных, соответствующие столбцы в соответствии с его классом заполняются, а остальные данные (или даже весь объект) помещаются в BLOB.
Самое замечательное в этом то, что если вы добавляете значение члена, которое не нужно искать или индексировать, только хранить, вам не нужно помещать его в столбец базы данных, поэтому вы не вносите никаких изменений в База данных вообще: она будет храниться в сериализованном BLOB. Единственное, что нужно сделать, это добавить значение по умолчанию для этого члена в коде десериализации, чтобы объекты этого класса, которые уже находятся в базе данных и не имеют этого члена, будут иметь приличное значение по умолчанию для него.
Вы также можете создавать версии своих форматов объектов, если хотите, они становятся более сложными.
Однако эта схема имеет некоторые недостатки:
Ограничения сложно применить:
- Вы можете применять ограничения только к полям, в которых есть столбец.
- поскольку некоторые столбцы встречаются только с некоторыми классами, базе данных необходимо немного знать о вашей иерархии классов.
Например, вы, вероятно, захотите поместить адреса в отдельную таблицу и добавить соответствующие поля (почтовый индекс, страну, улицу, номер и т. Д.): Размещение всего этого в вашей основной таблице добавит слишком много столбцов. Кроме того, в какой-то момент вы захотите добавить некоторых клиентов или другие вещи, которые находятся в другой таблице и также имеют адрес, поэтому лучше поместить адрес в отдельную таблицу и ссылаться на них.
То же самое для людей или компаний и т. Д.
Теперь у магазина есть адрес, а у корзины нет, я полагаю, поэтому вам придется указать в базе данных DDL, что строка из вашей таблицы должна ссылаться на адрес, если он имеет тип "магазин", но не тип " корзина».
Это может стать немного волосатым.
Также, например, если у вас есть 10 магазинов и 100 000 тележек, для производительности может быть интересно разделить столы, чтобы вы получили хороший маленький быстрый стол и один большой стол.
Теперь есть другие решения:
Например, вы можете поместить весь код и базовые члены в базовый класс, но сделать tableName атрибутом класса, который изменяется в производном классе. Таким образом, просто изменяя имя таблицы, весь код применяется к другой таблице, но вам не нужно ничего переписывать.
Тогда вы получаете 1 стол на класс.
Конечно, вы можете применить метод выше для каждой таблицы, если ваша иерархия классов становится более сложной.
Как выбрать между двумя?
В основном, если вы создаете веб-CMS и сохраняете в таблице объекты класса, производные от Node, такие как:
- Статья
- изображение с легендой
- Галерея
- и т. д.
Все эти объекты в основном одинаковые вещи.
Все они будут иметь заголовок, поле TextContent, принадлежат ParentNode и т. Д.
Если вы выполняете поиск по ключевому слову «foo» в TextContent, гораздо проще, если все объекты находятся в одной таблице.
Если вы хотите перечислить все дочерние элементы ParentNode для отображения их на веб-странице, также будет намного проще, если все будет в 1 таблице.
Так что в этом случае первый метод действительно выгоден.
Теперь в вашем случае объекты не так похожи.
Лично я бы даже не дал им тот же базовый класс.
Я бы создал Mixin с именами «ThingWithCoordinates» (может быть, что-то более короткое) и добавил бы это к классам.
Теперь, может быть, Пекарня находится достаточно близко от Магазина, чтобы унаследовать ее, но, скорее всего, нет тележек и стеллажей.
В вашем случае я бы определенно использовал несколько таблиц. И в каждой таблице, если вам нужно хранить несколько классов, я бы использовал первый метод.
Наиболее важным является то, что ваша иерархия классов (и, следовательно, таблицы) должна основываться на чем-то СООТВЕТСТВУЮЩИХ (автодилеры и пекарни являются магазинами), а не на общих чертах, которые существуют между объектами, которые на самом деле не имеют ничего общего (например, корзина и магазин). Для этого есть миксины для общего кода, но не базовые классы.