Как обеспечить целостность домена при использовании ORM - PullRequest
0 голосов
/ 26 марта 2019

В дополнение к объявлению типа столбцов, как обеспечить целостность домена?

ENUM() - вариант, однако он имеет недостатки с точки зрения SQL, а также с точки зрения Doctrine .

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

MariaDB [tracker]> select * from time_unit;
+------+-----------+----------+
| unit | name      | seconds  |
+------+-----------+----------+
| d    | Days      |    86400 |
| h    | Hours     |     3600 |
| i    | Minutes   |       60 |
| m    | Month     |  2592000 |
| q    | Quarter   | 10368000 |
| s    | Seconds   |        1 |
| w    | Week      |   604800 |
| y    | Year      | 31536000 |
+------+-----------+----------+
8 rows in set (0.01 sec)

MariaDB [tracker]> select * from sign;
+------+
| sign |
+------+
|   -1 |
|    1 |
+------+
2 rows in set (0.00 sec)

CREATE TABLE `agenda` (
  `id` int(11) NOT NULL,
  `time_value` smallint(6) DEFAULT NULL,
  `time_unit` varchar(1) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `sign` smallint(6) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_agenda_time_unit1_idx` (`time_unit`),
  KEY `fk_agenda_sign1_idx` (`sign`),
  CONSTRAINT `FK_5A9C89CF7106057E` FOREIGN KEY (`time_unit`) REFERENCES `time_unit` (`unit`),
  CONSTRAINT `FK_22ACC67D9F7E91FE` FOREIGN KEY (`sign`) REFERENCES `sign` (`sign`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

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

На уровне базы данных представлены отношения между сущностями по внешним ключам. Но с Doctrine вам никогда не придется (и никогда следует) работать с внешними ключами напрямую. Вы должны работать только с объекты, которые представляют внешние ключи через свои собственные идентификаторы.

Для обеспечения целостности домена следует ли использовать ENUM (), внешние ограничения для естественного ключа или какой-либо другой подход?

Ответы [ 2 ]

1 голос
/ 26 марта 2019

Это в основном вопрос стиля.Когда вы создаете схему, ссылочная целостность - это способ гарантировать качество.Есть и другие способы сделать это - например, модульные тесты, которые гарантируют, что система не примет значения «знака», отличные от 1 и -1.

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

Если вы действительно хотите, чтобы база данных проверяла записи, вы можете использовать перечисление или сообщить ORM, что столбец является целым числом, но все же создать внешний ключ.Является ли это хорошей идеей, снова зависит от стиля.Я очень предпочитаю "СУХОЙ" - не повторяйся.Если у вас есть логика для ограничения допустимых параметров для атрибута на уровне приложения, сфокусируйтесь на том, чтобы сделать это лучше, не повторяйте эту логику в схеме базы данных.Хотя это не так уж и сложно - если вы думаете, что люди получат доступ к базе данных за пределами вашего приложения, есть законное обоснование наличия внешнего ключа или перечисления.

Я думаю, что ваш time_unit - это больше, чем набор значений поиска - я предполагаю, что столбец «секунд» используется для преобразования единиц измерения.Здесь есть несколько вариантов, но опять-таки я бы хотел положиться на модульные тесты для проверки моей логики преобразования, и вы могли бы рассмотреть возможность сохранения их как констант в коде приложения, если именно там происходит логика преобразования.Затем вы можете сохранить модуль в виде столбца char в таблице повестки дня.

Это делает вашу логику постоянства проще и быстрее, но возлагает ответственность за проверку поведения на ваши модульные тесты, а не на вашу схему.

Я думаю, что цитата о том, что никогда не следует использовать внешние ключи напрямую, предназначена для того, чтобы предположить, что «нормальным» поведением с использованием вашего ORM было бы обращение к time_unit путем запроса объекта повестки дня (print agendaItem.time_unit.name), а не явного запросадля внешнего ключа и извлечения связанного объекта (timeUnitID = agendaItem.timeUnitID; print time_unit.findByID(timeUnitID).Я не думаю, что это общий совет против внешних ключей.

0 голосов
/ 26 марта 2019

ENUM () является опцией, однако она имеет недостатки с точки зрения SQL а также доктрина перспективы.

Для обеспечения целостности домена, если ENUM (), внешние ограничения для естественный ключ или какой-то другой подход будет использоваться?

Вы можете заменить тип данных MySQL / MariaDB

ENUM('1', '2', '3'); 

При более рациональном подходе.

    CREATE TABLE enum_data (
       position TINYINT
     , value CHAR(1)
    );

INSERT INTO enum_data (position, value) VALUES(1, '1');
INSERT INTO enum_data (position, value) VALUES(2, '2');
INSERT INTO enum_data (position, value) VALUES(3, '3');

И используйте это в своем столе

CREATE TABLE your_table (
   id INT ....
 , enum_data_id TINYINT
 ...
 ...
)

В других источниках вы также можете / должны также использовать FOREIGN KEY для обеспечения целостности данных с рациональным подходом.
Также использование дополнительной таблицы имеет преимущество перед ENUM.
Если вы хотите добавить, отредактировать, удалить из типа данных ENUM, вам потребуется использовать ALTER TABLE, который не требуется при использовании другой таблицы.

...