Doctrine one-to-one unidirectional

10,441

You need to change the JoinColumn name property to anything else but not id:

/**
 * @ORM\OneToOne(targetEntity="MySubEntity", cascade={"persist", "remove"})
 * @ORM\JoinColumn(name="mysubentity_id", referencedColumnName="id", nullable=true)
 */
private $mysubentity;

What does this do: JoinColumn tells doctrine in which database column the relation is saved. so if you call it mysub_id your main entity will have a column with that name in which the referencedColumn value will be persisted (id of your subEntity).

If you say the JoinColumn name is id which is already used by the primary key of your entity you have a conflict.

Edit:

I missed your point with sharing the same primary key. Is there any specific reason for this? But if you really need to do it for legacy reasons either look at

http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/composite-primary-keys.html#use-case-2-simple-derived-identity

or the possibility to generate the primary key value of your subEntity by yourself by changing the generation strategy (NONE or custom in this case)

http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/basic-mapping.html#identifier-generation-strategies

Share:
10,441
phpPhil
Author by

phpPhil

Lorem Ipsum.

Updated on July 21, 2022

Comments

  • phpPhil
    phpPhil almost 2 years

    In Symfony 3 with Doctrine I'm trying to get a one-to-one unidirectional relationship with both tables sharing the same primary key working. To do so I'm trying to replicate the example on the Doctrine Association Mapping page.

    However, the one-to-one uni documentation has no examples of setters and getters - and there is no definition of the id field on the target entity, either. So I tried to experiment around myself.

    These are my entities:

    class Country
    {
    
        /**
         * @var integer
         *
         * @ORM\Column(name="id", type="integer", precision=0, scale=0, nullable=false, unique=false)
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="IDENTITY")
         */
        private $id;
    
        /**
         * @ORM\OneToOne(targetEntity="MySubEntity", cascade={"persist", "remove"})
         * @ORM\JoinColumn(name="id", referencedColumnName="id", nullable=true)
         */
        private $mysubentity;
        [...]
        /**
         * @return MySubEntity
         */
        public function getMySubEntity()
        {
            return $this->mysubentity;
        }
    
        /**
         * @param MySubEntity $mysubentity
         */
        public function setMySubEntity($mysubentity)
        {
            $this->mysubentity = $mysubentity;
        }
    }
    
    class MySubEntity
    {
        /**
         * @var integer
         *
         * @ORM\Column(name="id", type="integer", precision=0, scale=0, nullable=false, unique=false)
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="IDENTITY")
         */
        private $id;
    
        [..]
    
        /**
         * Set id
         *
         * @param $id
         *
         * @return MySubEntity
         */
        public function setId($id)
        {
            $this->id = $id;
    
            return $this;
        }
    
        /**
         * Get id
         *
         * @return int
         */
        public function getId()
        {
            return $this->id;
        }
    }
    

    When I persist the country entity, I receive Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails. When inspecting the data I can see that Doctrine attempted to set the id of MySubEntity to 0.

    Does anybody have an idea what I need to do for the MySubEntity $id field to be auto-populated from the Country entity?

  • phpPhil
    phpPhil about 7 years
    You are completely right, there was not really a reason why I used the same Primary Key in both tables - even though that this is valid and should work with Doctrine in my opinion. I changed the schema and instead I added a new my_sub_entity_id column. Then I changed the annotations to reflect the new key name and it worked straight away. Thanks for your help!