2012-09-19 6 views
78

Sto sviluppando la mia applicazione utilizzando Zend Framework 2 e Dottrina 2.Qual è la differenza tra inversedBy e mappedBy?

Mentre scrittura annotazioni, non riesco a capire la differenza tra mappedBy e inversedBy.

Quando devo usare mappedBy?

Quando devo usare inversedBy?

Quando non dovrei usare nessuno dei due?

Ecco un esempio:

/** 
* 
* @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; 

Ho fatto una rapida ricerca ed ho trovato quanto segue, ma io sono ancora confuso:

risposta

127
  • mappedBy deve essere specificato sulla lato invertito di un (bidirezionale) associazione
  • inversedBy deve essere indicata nella parte possedere di un (bidirezionale) associazione

dalla documentazione doctrine:

  • ManyToOn e è sempre il lato proprietario di un'associazione bidirezionale.
  • OneToMany è sempre il lato inverso di un'associazione bidirezionale.
  • Il lato proprietario di un'associazione OneToOne è l'entità con la tabella contenente la chiave esterna.

Vedi http://docs.doctrine-project.org/en/latest/reference/unitofwork-associations.html

+1

Stranamente l'Analizzatore dottrina ha deciso di lasciare fuori l'esempio yaml di una relazione molti-a-uno mappatura bidirezionale, probabilmente il più comunemente usato! –

+2

@PeterWooster, la migliore pratica è usare le annotazioni, dato che hai tutte le informazioni sull'entità in un posto! –

+0

Questo vale anche per molte o molte relazioni. Per quelli: puoi scegliere tu stesso il lato proprietario di un'associazione many-to-many. – 11mb

20

In relazione bidirezionale ha sia un lato di appartenenza ed un lato inverso

mappedBy: mettere sul lato inverso di un rapporto bidirezionale Per fare riferimento al suo lato possedere

inversoData: inserire nel lato proprietario di una relazione bidirezionale Per fare riferimento al suo lato inverso

E

mappedBy attributo utilizzato con la dichiarazione mappatura OnetoOne, OneToMany o ManyToMany.

inverso con l'attributo utilizzato con la dichiarazione di mapping OneToOne, ManyToOne o ManyToMany.

: Il lato proprietario di una relazione bidirezionale il lato che contiene la chiave esterna.

c'è due di riferimento su inversedBy e mappedBy in Dottrina Documentazione: First Link, Second Link

+1

+1 per i collegamenti con alcuni esempi. – Marcos

38

Le risposte di cui sopra non erano sufficienti per me capire cosa stava succedendo, così dopo scavare in più penso di avere un modo di spiegarlo ha senso per le persone che hanno lottato come ho fatto per capire.

inversedBy e mappedBy sono utilizzati dal DOTTRINA INTERNO motore per ridurre il numero di query SQL ha a che fare per ottenere le informazioni necessarie. Per essere chiari se non si aggiunge inversedBy o mappedBy il codice funzionerà ancora ma non sarà ottimizzato.

Così, per esempio, guardate le classi inferiori:

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; 
} 

queste classi se si dovesse eseguire il comando per generare lo schema (ad esempio, bin/console doctrine:schema:update --force --dump-sql) si noterà che la tabella Categoria non ha una colonna su di esso per le attività. (questo perché non ha un'annotazione di colonna su di esso)

La cosa importante da capire qui è che le attività variabili sono solo lì in modo che il motore di dottrina interno possa utilizzare il riferimento sopra di esso che dice la sua mappedBy Category. Ora ... non essere confuso qui come lo ero io ... La categoria NON si riferisce al NOME DELLA CLASSE, si riferisce alla proprietà nella classe Task chiamata 'categoria $ protetta'.

Come saggio, sulla classe Compiti della categoria di proprietà $ menziona è inversedBy = "compiti", notare questo è plurale, questo non è il plurale del nome della classe, ma solo perché la proprietà è chiamata 'protetto $ tasks 'nella classe Category.

Una volta compreso questo diventa molto facile capire cosa stanno inversedBy e mappedBy e come usarli in questa situazione.

Il lato che fa riferimento alla chiave esterna come "attività" nel mio esempio ottiene sempre l'attributo inversedBy perché ha bisogno di sapere quale classe (tramite il comando targetEntity) e quale variabile (inversedBy =) su quella classe a 'lavoro indietro per così dire e ottenere le informazioni sulla categoria da. Un modo semplice per ricordare questo, è la classe che avrebbe foreignkey_id è quello che ha bisogno di essere inversedBy.

Dove come con la categoria e la sua proprietà $ tasks (che non è presente sulla tabella, solo una parte della classe per scopi di ottimizzazione) è MappedBy "tasks", crea la relazione ufficialmente tra le due entità in modo tale che la doctrina ora può tranquillamente utilizzare le istruzioni JOIN SQL invece di due istruzioni SELECT separate. Senza mappedBy, il motore doctrine non saprebbe dall'istruzione JOIN che creerà quale variabile nella classe 'Task' per inserire le informazioni sulla categoria.

Spero che questo lo spieghi un po 'meglio.

+4

Questo è molto ben spiegato e grazie per il vostro impegno. Sono venuto da Laravel Eloquent alla dottrina e questo è stato difficile per me capire la logica qui. Molto bene. 'La categoria NON si riferisce al NOME DELLA CLASSE, si riferisce alla proprietà nella classe Task chiamata 'categoria $ protetta' tutto ciò di cui avevo bisogno. Non ha solo risolto il mio problema, ma mi ha aiutato a capire. La migliore risposta IMO :-) –

+0

Grazie, mi ci è voluto un po 'per capirlo. Sono contento che l'abbia aiutato :). –

+0

Anch'io venivo da Eloquent, questo mi ha aiutato molto. il mio unico punto critico ora è come impostare il setter/getter per questo, sto ancora imparando le corde su di esso – Eman

1

5.9.1. Owning and Inverse Side

Per le associazioni molti-a-molti è possibile scegliere quale entità è la proprietà e quale parte inversa. C'è una semplice regola semantica per decidere quale lato è più adatto per essere il lato proprietario dal punto di vista degli sviluppatori. Devi solo chiedertelo, quale entità è responsabile della gestione della connessione e sceglierla come il proprietario.

Prendi un esempio di due entità Articolo e tag. Ogni volta che si desidera collegare un articolo a un tag e viceversa, è soprattutto l'articolo che è responsabile di questa relazione. Ogni volta che aggiungi un nuovo articolo, vuoi collegarlo con tag esistenti o nuovi. La tua forma di creazione dell'articolo probabilmente supporterà questa nozione e permetterà di specificare direttamente i tag. Questo è il motivo per cui si dovrebbe scegliere l'articolo come possedere lato, in quanto rende il codice più comprensibile:

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

Problemi correlati