Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Doctrine - OneToOne Unidirectional vs OneToOne Bidirectional

I joust started playing around with Doctrine ORM library, and Im learning about all associations between tables.

So Im stuck with differences in Unidirectional and Bidirectional relation.

As I get it, Unidirectional relation has primary key only on one side, and that side is owning side right? And Bidirectional relation have primary key in both tables and therefore you can have relation from both sides, and set constrains on both sides.

Now, Im reading through Doctrine documentation about relations and there you have: Unidirectional and Bidirectional associations.

But they produce the same SQL, and the same tables with the same primary key-s and constrains. So I dont really see any difference in those two. And both examples have primary key on one side.

As I get it the true Bidirectional relation should have primary keys in both tables pointing to the other table right? And with given example on Doctrine documentation that is not the case. Both examples give the same result and are the same.

So what I did, is this, lets say I have User and Card Entity, and want relation to be OneToOne Bidirectional.

    /**
 * @Entity
 * @Table(name="users")
 */

class User
{
    /**
     * @Id
     * @GeneratedValue
     * @Column(type="bigint")
     */
    protected $id;

    /**
     * @OneToOne(targetEntity="Card", mappedBy="User")
     * @JoinColumn(name="card_id", referencedColumnName="id")
     */
    protected $card;

    /**
     * @Column(name="user_name", type="string")
     */
    protected $userName;

    /**
     * @Column(name="user_pass", type="string")
     */
    protected $userPass;
}

    /**
 * @Entity
 * @Table(name="cards")
 */

class Card
{
    /**
     * @Id
     * @GeneratedValue
     * @Column(type="bigint")
     */
    protected $id;

    /**
     * @OneToOne(targetEntity="User", inversedBy="Card")
     * @JoinColumn(name="user_id", referencedColumnName="id")
     */
    protected $user;

    /**
     * @Column(name="post_title", type="string")
     */
    protected $cardType;
}

The difference here is I wrote @JoinColumn in both objects/entities. And in Doctrine example there is only one. Now I would get what I think is Bidirectional relation. If i look at EER diagram, I can see one line pointing from user to card, and the other from card to user.

So basicly did I get this right? Is the Doctrine documentation wrong? :D How would Bidirectional OneToOne relation look in EER diagram?

Thanks!

like image 374
otporan Avatar asked Oct 08 '12 11:10

otporan


People also ask

What is a bidirectional relationship SQL?

In a bidirectional relationship, each entity has a relationship field or property that refers to the other entity. Through the relationship field or property, an entity class's code can access its related object. If an entity has a related field, the entity is said to “know” about its related object.

What is owning side and inverse side?

And it's easy to remember: the owning side is where the foreign key column lives in the database. In this case, the answer table will have a question_id column so this is the "owning" side. The OneToMany side is called the inverse side.


2 Answers

The only difference is in the PHP class interface, i.e. in the presence or absence of the property that points back to the owner (e.g. the $customer property in the mentioned Doctrine example). In other words Doctrine just needs to know whether it should take care about a single property ($shipping) or two properties ($cart and $customer). There is no other difference. Therefore, the SQL code is the same (because one foreign key is sufficient for representing any 1:N relationship) and there would no difference in EER diagram neither (because in EER you typically do not solve such PHP-related implementation details).

like image 51
radkovo Avatar answered Oct 21 '22 21:10

radkovo


Unidirectional and bidirectional have nothing to do with the background algorithm how to create these connections in the database layer.

All they talk about is how the connections can be used. In an unidirectional relationship you can access the target only from one site. An bidirectional relationship allows the connection to be called from two (both) sides.

So in an unidir. rel. model_a can get to model_b, but model_b cant get to model_a (without extra work). If you now use a bidir. rel both models can access each other without problems

In doctrine terms, a unidirectional relationship defines a $modelA->getModelB() method, but not a $modelB->getModelA() method, whereas a bidirectional relationship defines both methods (or accessors, however you want to call them)

in an uml diagram it would look like this:

unidirectional
modelA --X------> modelB

bidirectional
modelA <--------> modelB
like image 42
Criss Avatar answered Oct 21 '22 23:10

Criss