简体   繁体   中英

unidirectional vs bidirectional in one-to-one relationship

I was reading Doctrine docs and I came across these concepts and got confused.

I have these tables:

Users -> id, role, email, username, password

Students -> id, user_id, fname, lname

Teachers -> id, user_id, fname, designation

user_id is the foreign key from Users table. So is this supposed to be a unidirectional relation or bidirectional?

How do they differ?

Can someone please provide real world examples for both?

Doctrine docs says here that Doctrine will only check the owning side of an association for changes. What does that mean? What kind of changes?

In general, you can use both unidirectional or bidirectional relationships whenever you want. You design your code due to the use you will do of it. That is, for example, if you are declaring an unidirectional relationship oneToOne is because you only need to have the information in one side. At the contrary side, if you need to access from both entities the information about the other entity, you need to declare your bidirectional relationship. For example:

Supposing that your relationship User-Teacher is OneToOne.

Case 1: You'll want to know if a user is a teacher and also you'll need to know which user is related to a Teacher entity => you use bidirectional relationship.

/** @Entity */
class User
{
    // ...

    /**
     * @OneToOne(targetEntity="Teacher", mappedBy="user")
     */
    private $teacher;

    // ...
}

/** @Entity */
class Teacher
{
    // ...

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

    // ...
}

Default tables would look sth like:

CREATE TABLE Teacher (
    id INT AUTO_INCREMENT NOT NULL,
    user_id INT DEFAULT NULL,
    PRIMARY KEY(id)
) ENGINE = InnoDB;
CREATE TABLE User (
    id INT AUTO_INCREMENT NOT NULL,
    PRIMARY KEY(id)
) ENGINE = InnoDB;
ALTER TABLE Teacher ADD FOREIGN KEY (user_id) REFERENCES User(id);

Case 2: You need to access the teachers related user but you'll never need to know the users that are teachers, so you declare only the part of the teacher side.

Reference: http://docs.doctrine-project.org/en/2.0.x/reference/association-mapping.html#one-to-one-unidirectional

There are a few restrictions, mainly in oneToMany relationships. In general, I'll advice you to use bi-directional relationships.

"Doctrine docs says here that Doctrine will only check the owning side of an association for changes. What does that mean? What kind of changes?"

I'm not totally sure of this, but I can tell you what I understand of that: when you are flushing your changes in your entities (after changing sth on them and executing $entityManager->flush()), it will only check your changes from the main entity in the relationship, that is, it won't check in both entities if you have changed sth in the other one, only in the main one in the relationship. So you must declare as the owner side that one that is the "base" one, and not at the contrary. For example, in the previous example, if you changed your user entity from your teacher entity, Doctrine won't take it in account because User is the owner side.

ex:

$teacher->getUser()->setName('john'); //Doctrine won't check for this change
$user->getTeacher()->setStatus('dismissed'); //Doctrine will track this change

As I tell you, I've not tested that kind of cases because I usually declare well my relationships (your FK will define which is the owner side, in this case User). It won't be difficult to make a test and confirm it, anyhow.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM