Составные первичные ключи или суррогатный первичный ключ для сущностей отношений (сущностей, которые также являются отношениями) в Doctrine2
У меня есть большая база данных, где у меня есть сущности, которые являются отношениями. Это как раз из-за следующего комментария в руководстве к Доктрине 2: мне нужно было хранить дополнительные атрибуты в наших отношениях, и из-за этого отношение стало сущностью.
Обычно мы используем сгенерированные идентификаторы для сущностей и составные ключи для отношений. В этом случае сущность является отношением, что делает выбор немного более сложным...
Помните о том, что я не говорю о естественных ключах здесь. Я использую составной ключ, который состоит из идентификаторов, которые являются целыми числами, созданными с использованием стратегии автоматического приращения в их соответствующих объектах-владельцах.
Я вижу некоторые недостатки использования составных первичных ключей на объекте отношений:
- Мне нужно вызвать постоянный вызов между созданием сущностей и их отношений (чтобы сгенерировать ключ на сущности, прежде чем я смогу использовать его в качестве внешнего ключа в моем составном первичном ключе).
- Чтобы связать дополнительные сущности с сущностью отношения, нам нужно снова добавить столбцы для идентификаторов, используемых в составном ключе в этих сущностях. Если бы я использовал суррогатный первичный ключ, мне нужен только один столбец с этим идентификатором.
Я вижу также некоторые преимущества использования составных ключей, например:
- Они устраняют необходимость в определенных запросах объединений, вместо этого вы можете создавать запросы для непосредственного извлечения информации с использованием составных ключей.
Но наиболее важным аргументом для использования составных ключей на данный момент является следующее:
- Когда связь между пользователем и SomeEntity будет удалена, а затем снова создана (сценарий, который может произойти в нашей модели приложения), нам также необходимо восстановить доступ ко всем другим связанным объектам. Если связь между пользователем и SomeEntity создается с использованием стратегии автоинкремента на суррогатном первичном ключе. Восстановленные (новые) отношения получат новый первичный ключ (id). Из-за этого связанные сущности (хранящиеся с использованием "старого" ключа) больше не доступны. Если бы я использовал составной ключ в отношении, я мог бы просто восстановить отношение (оно получает те же значения составного ключа), и таким образом я снова получил бы доступ к другим связанным объектам.
Есть ли люди, которые имеют опыт работы с подобным сценарием? Есть ли другие решения, чтобы заставить это работать должным образом. Есть ли какие-то важные недостатки или преимущества (при использовании Doctrine ORM), которые я упустил.
Я могу придумать одну альтернативу, добавив состояние в отношение User SomeEntity. Вместо удаления записи мы могли бы изменить состояние на отключено, включено. Таким образом, мы можем использовать суррогатный ключ вместо составного, потому что запись никогда не будет удалена...
Обратная связь с благодарностью...
Для людей, которые заинтересованы, было также хорошее обсуждение суррогатных и составных ключей на переполнение стека здесь: (нажмите)
1 ответ
Я бы предложил сделать ваши два внешних ключа составным первичным ключом.
Ваша ассоциативная сущность будет идентифицироваться по идентификаторам ее двух отношений.
Теоретически, модуль DoOtine UnitOfWork/CommitOrderCalculator должен всегда вставлять элементы в правильном порядке, и, таким образом, вам не придется иметь дело с постоянным порядком.
Ваше отображение будет выглядеть так в конце (пример аннотации):
<?php
class UserGroup
{
/**
* @ORM\ManyToOne(targetEntity="User")
* @ORM\Id
**/
public $user;
/**
* @ORM\ManyToOne(targetEntity="Group")
* @ORM\Id
**/
public $group;
}