Symfony2 OneToOne relationship becomes either a Un

2019-05-20 22:12发布

问题:

I'm taking my first steps in Symfony2 entity relations. I have an entity installation, which each has one meter, and one monitor.

This translates to a uni-directional relationship, which I defined as such:

    /**
     *
     * @ORM\OneToOne(targetEntity="InfoMeter")
     * @ORM\JoinColumn(name="meterid", referencedColumnName="id")
     */
    private $meter;  

    /**
     *
     * @ORM\OneToOne(targetEntity="InstallationsRtu")
     * @ORM\JoinColumn(name="monitorid", referencedColumnName="id")
     */
    private $monitor;

Each monitor can only be assigned to one installation. Each meter can be assigned to multiple installations.

When I update my database (app/console doctrine:schema:update --force), there are two outcomes.
In case of the monitor:
Everything goes alright, schema gets updated with a keyname which is prefixed by 'UNIQ_'.

In case of the meter: I get the following error

PDOException]                                                                                             
  SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1' for key 'UNIQ_43D26968860BE41D'

When I look at the table structure after this error occured, I can't find that mentioned constraint, but I do find FK_43D26968860BE41D, i.e. the same, but prefixed with 'FK'.

In the installation table, I now have these listed:

Keyname                 Type    Unique  Packed  Field     Cardinality
PRIMARY                 BTREE   Yes No  id    2 
UNIQ_43D26968701EC1AB   BTREE   Yes No  monitorid 2     
FK_43D26968860BE41D BTREE   No  No  meterid   2

So one saying 'Unique=Yes', and the other saying 'Unique=No'.

To arrive at my question:
How can I decide whether it is a UNIQ index or a FK index? I assume that Doctrine saw that currently each monitorid is unique in the installation table, but that each meterid occurs several times in the installation table.
Hence it went with UNIQ for the first, and FK for the latter. But can I control this somehow?

回答1:

If one metter can be assigned to multiple installations, shouldn't you define a OneToMany relationship?

In your installation entity:

/**
 * @ORM\ManyToOne(targetEntity="InfoMeter", inversedBy="installations")
 * @ORM\JoinColumn(name="infometer_id", referencedColumnName="id")
 */
protected $info_meter;

And then in your InfoMeter entity:

/**
 * @ORM\OneToMany(targetEntity="Installation",mappedBy="info_meter")
 */
protected $installations;

Besides, you should add the following to your InfoMeter class constructor:

function __construct() {
   [...]
   $this->installations = new \Doctrine\Common\Collections\ArrayCollection();
}

I'm sure this approach can be improved depending on how you want the relation between "installations" and "meters", but this should work.