Составные первичные ключи или суррогатный первичный ключ для сущностей отношений (сущностей, которые также являются отношениями) в Doctrine2

У меня есть большая база данных, в которой есть сущности, являющиеся отношениями. Это именно из-за следующий комментарий в руководстве по Doctrine 2: Мне нужно было хранить дополнительные атрибуты в наших отношениях, и из-за этого отношение стало сущностью.

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

Имейте в виду, что я не говорю здесь о естественных ключах. Я использую составной ключ, который состоит из идентификаторов, которые представляют собой целые числа, созданные с использованием стратегии автоматического увеличения в соответствующих объектах-владельцах.

Я вижу некоторые недостатки использования составных первичных ключей в сущности отношения:

  • Мне нужно вызвать persist между созданием сущностей и их отношений (чтобы сгенерировать ключ для сущности, прежде чем я смогу использовать его в качестве внешнего ключа в своем составном первичном ключе).
  • Чтобы связать дополнительные сущности с сущностью отношения, нам нужно снова добавить столбцы для идентификаторов, используемых в составном ключе, в этих сущностях. Если бы я использовал суррогатный первичный ключ, мне нужен был бы только один столбец, содержащий этот идентификатор.

Я также вижу некоторые преимущества использования составных ключей, например:

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

Но сейчас самый важный аргумент в пользу использования составных ключей заключается в следующем:

  • Когда связь между пользователем и SomeEntity удаляется, а затем создается снова (сценарий, который может произойти в нашей модели приложения), нам также необходимо восстановить доступ ко всем другим связанным объектам. Если связь между пользователем и SomeEntity создается с использованием стратегии автоматического увеличения суррогатного первичного ключа. Восстановленные (новые) отношения получат новый первичный ключ (id). Из-за этого связанные сущности (сохраненные с использованием «старого» ключа) больше не доступны. Если бы я использовал составной ключ для отношения, я мог бы просто восстановить связь (он получает те же значения составного ключа), и благодаря этому я снова сразу же получу доступ к другим связанным объектам.

Есть ли люди, которые сталкивались с подобным сценарием? Есть ли другие решения, чтобы заставить это работать должным образом. Есть ли какие-то важные недостатки или преимущества (при использовании Doctrine ORM), которые я упустил.

Я могу придумать одну альтернативу, добавив состояние в отношение User SomeEntity. Вместо удаления записи мы могли бы изменить состояние на отключено, включено. Таким образом, мы могли бы использовать суррогатный ключ вместо составного ключа, потому что запись никогда не будет удалена ...

Мы очень ценим обратную связь ...

Для заинтересованных людей также было хорошее обсуждение суррогатных и составных ключей в Stack Overflow здесь: (нажмите)




Ответы (1)


Я предлагаю сделать ваши два внешних ключа составным первичным ключом.

Сущность вашей ассоциации будет идентифицироваться по идентификаторам двух ее отношений.

Теоретически Doctrine UnitOfWork / CommitOrderCalculator должен быть хотя бы для вставки элементов в правильном порядке, и, таким образом, вам не придется иметь дело с постоянным порядком.

В конце ваше отображение будет выглядеть так (пример аннотации):

<?php

class UserGroup
{
    /**
      * @ORM\ManyToOne(targetEntity="User")
      * @ORM\Id
     **/
    public $user;

    /**
      * @ORM\ManyToOne(targetEntity="Group")
      * @ORM\Id
     **/
    public $group;
}
person Florian Klein    schedule 17.05.2013