inversedBy와 mappingBy의 차이점은 무엇입니까?


102

Zend Framework 2와 Doctrine 2를 사용하여 애플리케이션을 개발 중입니다.

주석을 작성하는 동안 다음의 차이점을 이해할 수 없습니다. mappedByinversedBy .

언제 사용해야합니까 mappedBy 합니까?

언제 사용해야합니까 inversedBy 합니까?

둘 다 언제 사용해야합니까?

다음은 예입니다.

 /**
 *
 * @ORM\OneToOne(targetEntity="\custMod\Entity\Person", mappedBy="customer")
 * @ORM\JoinColumn(name="personID", referencedColumnName="id")
 */
protected $person;

/**
 *
 * @ORM\OneToOne(targetEntity="\Auth\Entity\User")
 * @ORM\JoinColumn(name="userID", referencedColumnName="id")
 */
protected $user;

/**
 *
 * @ORM\ManyToOne (targetEntity="\custMod\Entity\Company", inversedBy="customer")
 * @ORM\JoinColumn (name="companyID", referencedColumnName="id")
 */
protected $company;

빠른 검색을했고 다음을 찾았지만 여전히 혼란 스럽습니다.

답변:


159
  • 반전 된 쪽에서 mappingBy 를 지정해야합니다.(양방향) 연관의
  • inversedBy 는 (양방향) 연관 의 소유 측 에서 지정되어야합니다.

교리 문서에서 :

  • ManyToOne은 항상 양방향 연결의 소유 측입니다.
  • OneToMany는 항상 양방향 연결의 반대쪽입니다.
  • OneToOne 할당의 소유 측은 외래 키를 포함하는 테이블이있는 엔티티입니다.

참조 https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/unitofwork-associations.html를


1
이상하게도 Doctrine 문서 작성자는 아마도 가장 일반적으로 사용되는 다 대일 양방향 매핑의 yaml 예제를 생략하기로 결정했습니다!
Peter Wooster 2013 년

4
@PeterWooster, 모범 사례는 Annotations를 사용하는 것입니다. 엔터티에 대한 모든 정보를 한곳에 모았습니다!
Andreas Linden

이것은 또한 다 대다 관계에도 적용됩니다. 이를 위해 다 대다 연관의 소유 측면을 직접 선택할 수 있습니다.
11메가바이트

5
널리 사용되는 @AndreasLinden은 모범 사례를 의미하지 않습니다. 주석을 사용하여 즉시 코드를 작성하는 것은 모범 사례로 간주 될 수 없으며 PHP 네이티브가 아니며 모든 프레임 워크에 기본적으로 포함되어 있지도 않습니다. 엔티티에 대한 모든 정보를 한곳에 모아 두는 것은 반론입니다. 모든 코드를 한 곳으로 그룹화하는 것이 좋은 일이기 때문에? 프로젝트의 조직을 작성하고 유지하고 축소하는 것은 고통입니다. 모범 사례? 이런.
JesusTheHun

3
@JesusTheHun 당신은 사과와 배를 비교하고 있습니다. "모든 코드"는 "기업에 대한 모든 정보"매우 매우 다르다)
안드레아스 린든

55

위의 답변은 무슨 일이 일어나고 있는지 이해하기에 충분하지 않았기 때문에 더 자세히 살펴보면 내가 이해했던 것처럼 어려움을 겪은 사람들에게 이해가 될만한 설명 방법이 있다고 생각합니다.

inversedBy 및 mappingBy는 필요한 정보를 얻기 위해 수행해야하는 SQL 쿼리 수줄이기 위해 INTERNAL DOCTRINE 엔진에서 사용됩니다 . inversedBy 또는 mappingBy를 추가하지 않으면 코드는 계속 작동하지만 최적화 되지는 않습니다 .

예를 들어, 아래 클래스를보십시오.

class Task
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="task", type="string", length=255)
     */
    private $task;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="dueDate", type="datetime")
     */
    private $dueDate;

    /**
     * @ORM\ManyToOne(targetEntity="Category", inversedBy="tasks", cascade={"persist"})
     * @ORM\JoinColumn(name="category_id", referencedColumnName="id")
     */
    protected $category;
}

class Category
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     */
    private $name;

    /**
     * @ORM\OneToMany(targetEntity="Task", mappedBy="category")
     */
    protected $tasks;
}

이러한 클래스는 명령을 실행하여 스키마 (예 :)를 생성 bin/console doctrine:schema:update --force --dump-sql하는 경우 Category 테이블에 작업에 대한 열이 없음을 알 수 있습니다. (이것은 열 주석이 없기 때문입니다)

여기서 이해해야 할 중요한 점은 변수 작업이 거기에만 있으므로 내부 교리 엔진이 그 위에있는 mappingBy Category라고하는 참조를 사용할 수 있다는 것입니다. 자 ... 여기에서 내가 그랬던 것처럼 혼동 하지 마십시오 ... Category는 CLASS NAME을 참조 하지 않으며 'protected $ category'라는 Task 클래스의 속성을 참조합니다.

마찬가지로, Tasks 클래스에서 속성 $ category는 그것이 inversedBy = "tasks"라고 언급합니다. 이것은 복수형이라는 것을 알 수 있습니다. 이것은 CLASS NAME의 복수형이 아닙니다. 그러나 속성이 Category에서 'protected $ tasks'라고 불리기 때문입니다. 수업.

이것을 이해하면 inversedBy와 mappingBy가하는 일과이 상황에서 어떻게 사용하는지 이해하기가 매우 쉬워집니다.

내 예제에서 'tasks'와 같은 외래 키를 참조하는 쪽은 항상 inversedBy 속성을 가져옵니다. 말하고 카테고리 정보를 얻으십시오. 이것을 기억하는 쉬운 방법은 foreignkey_id가있는 클래스가 inversedBy가 필요한 클래스라는 것입니다.

범주 및 해당 $ tasks 속성 (테이블에없는 것은 최적화 목적을위한 클래스의 일부만 기억)이 MappedBy 'tasks'인 경우, 이것은 두 엔티티 간의 관계를 공식적으로 생성하여 교리가 이제 안전하게 수행 될 수 있도록합니다. 두 개의 개별 SELECT 문 대신 JOIN SQL 문을 사용합니다. mappingBy가 없으면 교리 엔진은 JOIN 문을 통해 'Task'클래스에 어떤 변수를 만들어 카테고리 정보를 넣을지 알 수 없습니다.

이것이 조금 더 잘 설명되기를 바랍니다.


6
이것은 매우 잘 설명되어 있으며 귀하의 노력에 감사드립니다. 나는 Laravel Eloquent에서 교리로 왔고 여기에서 논리를 이해하기가 어려웠습니다. 잘 했어. Category is NOT referring TO THE CLASS NAME, its referring to the property on the Task class called 'protected $category'내가 필요한 모든 것. 그것은 내 문제를 해결했을뿐만 아니라 이해하는 데 도움이되었습니다. 최고의 답변 IMO :-)
The Alpha

1
저도 Eloquent에서 왔는데 이것은 저에게 큰 도움이되었습니다. 내 유일한 고집 포인트는 이것에 대한 setter / getter를 설정하는 방법입니다. 나는 여전히 그것에 대한 로프를 배우고 있습니다
Eman

1
네, 정말 쉽고 자동화 된 도구도 있습니다. 나중에 저와 채팅을 시작하면 제가 도와 드릴 수 있습니다
Joseph Astrahan 17 년

1
이 답변을 확인하십시오. stackoverflow.com/questions/16629397/…
Joseph Astrahan

1
symfony.com/doc/current/doctrine/associations.html , 이것은 실제로 배우는 것이 더 낫습니다. 심포니는 교리를 사용하므로 동일한 것을 가르칩니다.
Joseph Astrahan 2017 년

21

양방향 관계에는 소유 측과 반대 측이 모두 있습니다.

mappingBy : 양방향 관계의 반대쪽에 넣어 자신의 쪽을 참조하기 위해

inversedBy : 양방향 관계의 소유 측에 넣습니다. 반대 측을 참조합니다.

mappedBy의 속성은 OneToOne, OneToMany, 또는 ManyToMany 매핑 선언으로 사용된다.

inversedBy의 OneToOne, ManyToOne, 또는 ManyToMany 매핑 선언으로 사용되는 속성.

주의 사항 : 외래 키를 포함하는 쪽의 양방향 관계의 소유 쪽.

inversedBy 및 mappingBy에 대한 두 가지 참조가 Doctrine Documentation에 있습니다 : First Link , Second Link


1
링크가 죽었나요?
Scaramouche

2

5.9.1. 소유 및 역측

다 대다 연결의 경우 어떤 엔터티가 소유하고 어떤 엔터티가 반대쪽인지 선택할 수 있습니다. 개발자의 관점에서 어느 쪽이 소유 쪽이 더 적합한 지 결정하는 매우 간단한 의미 규칙이 있습니다. 연결 관리를 담당하는 엔티티가 누구인지 스스로에게 물어보고이를 소유 측으로 선택하기 만하면됩니다.

두 항목 기사 및 태그의 예를 살펴 보겠습니다. 기사를 태그에 연결하거나 그 반대로 연결하려고 할 때마다이 관계를 담당하는 것은 대부분 기사입니다. 새 기사를 추가 할 때마다 기존 또는 새 태그와 연결하려고합니다. 기사 작성 양식은 아마도이 개념을 지원하고 태그를 직접 지정할 수 있습니다. 이것이 코드를 더 이해하기 쉽게 만드는 기사를 소유 측으로 선택해야하는 이유입니다.

http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.