Сгенерируйте ID-ключи в таблице с составными ключами, используя Doctrine2 и Symfony2.

У меня в БД есть несколько таблиц с составными ключами, см. рисунок ниже:

Таблицы с составными ключами

Как вы можете видеть, в этом случае есть interest и klists, которые имеют свои собственные id, но также имеют kuser в качестве ключа. Документы Doctrine говорят, что они поддерживают почти все варианты использования составных ключей, но каждый объект с составным ключом не может использовать генератор идентификаторов, отличный от «ASSIGNED». Это означает, что поля ID должны иметь свои значения, установленные до того, как вы вызовете EntityManager#persist($entity). Когда я пытаюсь определить какие-либо объекты, связанные с этими таблицами, я получаю сообщение об ошибке, потому что Doctrine не позволяет этого:

  /**
   * @ORM\Id
   * @ORM\Column(name="id", type="integer", nullable=false)
   * @ORM\GeneratedValue(strategy="AUTO")
   */
  protected $id;

  /**
   * @ORM\Id      
   * @ORM\ManyToOne(targetEntity="UserBundle\Entity\User", inversedBy="users" )      
   * @ORM\JoinColumn(name="kuser", referencedColumnName="id")   
   */
   protected $kuser; 

Я знаю, что могу запустить некоторый код, используя обратный вызов жизненного цикла, но не знаю, как и где, поэтому мне нужна помощь здесь, кто-нибудь может сказать мне или указать мне правильный путь?


person Reynier    schedule 27.08.2013    source источник
comment
Почему именно вам нужно, чтобы id и kuser были составными? Идентификатор AutoIncremented уже будет уникальным. Зачем добавлять kuser в смесь? Просто удалите ORM\Id из kuser.   -  person Cerad    schedule 27.08.2013
comment
@Cerad, потому что это тоже должен быть КЛЮЧ, я не могу удалить   -  person Reynier    schedule 27.08.2013
comment
kuser все еще может быть ключом. Он просто будет содержать все, что находится в kuser.id, который также уникален. Доктрина установит его для вас во время сохранения. Doctrine также создаст для него индекс и позаботится о каскадировании. И если хотите, вы также можете дать ему уникальное ограничение. Я думаю, что вы, возможно, слишком много блуждали по пути составного ключа. Единственный раз, когда вы действительно видите это в Doctrine 2, это сгенерированная таблица ManyToMany без дополнительных атрибутов.   -  person Cerad    schedule 27.08.2013
comment
@Cerad, значит, таблица kuser_has_klists находится в ManyToManycase? Я немного потерялся в этом месте   -  person Reynier    schedule 27.08.2013


Ответы (1)


Вернуться к основам. Я предлагаю начать здесь: http://docs.doctrine-project.org/en/latest/reference/association-mapping.html

class KUser
{
    /**
     * @ORM\Id
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

class Interest
{
      /**
       * @ORM\Id
       * @ORM\Column(name="id", type="integer", nullable=false)
       * @ORM\GeneratedValue(strategy="AUTO")
       */
      protected $id;

      /**      
       * @ORM\ManyToOne(targetEntity="UserBundle\Entity\KUser")      
       * @ORM\JoinColumn(name="kuser_id", referencedColumnName="id")   
       */
      protected $kuser; 

Это все, что вам нужно для установления односторонней ManyToOne связи между Interest и KUser. Если вам нужна двунаправленность, добавьте свойство $interests в KUser и установите inversedBy в Interest.kuser.

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

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

class KUserHasKLists
{
      /**
       * @ORM\Id
       * @ORM\Column(name="id", type="integer", nullable=false)
       * @ORM\GeneratedValue(strategy="AUTO")
       */
      protected $id;

      /**      
       * @ORM\ManyToOne(targetEntity="UserBundle\Entity\KUser")      
       * @ORM\JoinColumn(name="kuser_id", referencedColumnName="id")   
       */
      protected $kuser; 

      /**      
       * @ORM\ManyToOne(targetEntity="UserBundle\Entity\KList")      
       * @ORM\JoinColumn(name="klist_id", referencedColumnName="id")   
       */
      protected $klist; 

Но опять же, начните с простого отношения и убедитесь, что вы понимаете, что происходит. Сделайте себе несколько функциональных тестов, если вам удобно работать с phpunit. Если нет, создайте себе команду Symfony, чтобы вы могли экспериментировать с этим из командной строки.

person Cerad    schedule 27.08.2013