Quando usare inversa = false sui rapporti NHibernate / Hibernate OneToMany?
-
21-08-2019 - |
Domanda
Ho cercato di fare i conti con l'attributo inversa di Hibernate, e sembra essere solo una di quelle cose che è concettualmente difficile.
Il succo che ottengo è che quando si ha un controllante (ad es Parent) che ha una collezione di oggetti figlio utilizzando un uno-a-molti la mappatura, l'impostazione inverse = true sulla mappatura dice a Hibernate che 'l'altro lato (il Bambino) ha la responsabilità di aggiornarsi per mantenere il riferimento chiave esterna nella sua tabella'.
In questo modo sembra avere 2 vantaggi quando si tratta di aggiungere i bambini alla raccolta nel codice, e quindi salvare la Capogruppo (con cascata tutti insieme): si salva un colpo inutile sul database (perché senza set inversa, Hibernate pensa che ha due posti per aggiornare il rapporto FK), e secondo i documenti ufficiali :
Se la colonna di un associazione è dichiarata NOT NULL, NHibernate può causare vincolo violazioni quando crea o aggiorna l'associazione. Impedire questo problema, è necessario utilizzare un associazione bidirezionale con il molti valutate fine (l'insieme o in borsa) contrassegnato come inverse = "true".
Questo sembra tutto per dare un senso finora. Quello che non capisco è questo:? Quando si non desiderano utilizzare inverse = true su una relazione uno-a-molti
Soluzione
Come dice Matthieu, l'unico caso in cui non si vorrebbe impostare inverse = true è dove non ha senso per il bambino di essere responsabile per l'aggiornamento stesso, come ad esempio nel caso in cui il bambino non è a conoscenza di suo genitore.
Consente di cercare un mondo reale, e non ad esempio affatto forzato:
<class name="SpyMaster" table="SpyMaster" lazy="true">
<id name="Id">
<generator class="identity"/>
</id>
<property name="Name"/>
<set name="Spies" table="Spy" cascade="save-update">
<key column="SpyMasterId"/>
<one-to-many class="Spy"/>
</set>
</class>
<class name="Spy" table="Spy" lazy="true">
<id name="Id">
<generator class="identity"/>
</id>
<property name="Name"/>
</class>
Spymasters possono avere delle spie, ma spie mai sapere chi è il loro capo delle spie è, perché non abbiamo incluso la relazione molti-a-uno nella classe spia. Inoltre (comodamente) una spia può girare canaglia e così non ha bisogno di essere associato ad un capo delle spie. Siamo in grado di creare entità come segue:
var sm = new SpyMaster
{
Name = "Head of Operation Treadstone"
};
sm.Spies.Add(new Spy
{
Name = "Bourne",
//SpyMaster = sm // Can't do this
});
session.Save(sm);
In questo caso si dovrebbe impostare la colonna FK per essere annullabile perché l'atto di sm risparmio sarebbe inserire nella tabella spymaster e la tabella della spia, e solo dopo che sarebbe poi aggiornare la tabella Spy per impostare l'FK. In questo caso, se dovessimo impostare inverse = true, l'FK sarebbe mai aggiornato.
Altri suggerimenti
Nonostante la risposta di alto votato accettato, ho un altro risposta.
Si consideri un diagramma delle classi con queste relazioni:
Parent => list of Items Item => Parent
Nessuno mai ha detto, che la voce => relazione padre è ridondante alla relazione padre => Articoli. Un elemento potrebbe fare riferimento a qualsiasi genitore.
Ma nell'applicazione, si sa che i rapporti sono ridondanti . Voi sapete che i rapporti non devono essere conservati separatamente nel database. Così si decide di riporlo in un chiave singola esteri , indicando dalla voce alla Capogruppo. Questa informazione minima è sufficiente per costruire la lista e il riferimento posteriore.
Tutto quello che devi fare per mappare questo con NH è:
- utilizzare la stessa chiave esterna per entrambe le relazioni
- dire che uno NH (elenco) è ridondante all'altra e potrebbe essere ignorato quando memorizzare l'oggetto. (Questo è ciò che in realtà NH fa con
inverse="true"
)
Questi sono i pensieri che sono rilevanti per l'inversa. Nient'altro. E non è una scelta, c'è un solo modo di una corretta mappatura.
La spia Problema : Si tratta di una discussione completamente diversa se si vuole sostenere un riferimento dal Item alla Capogruppo. Questo è fino al vostro modello di business, NH non prende alcuna decisione in questo. Se una delle relazioni manca, c'è naturalmente nessuna ridondanza e nessun uso di inversa.
Abuso: Se si utilizza inverse = "true" su una lista che non ha alcuna ridondanza nella memoria, semplicemente non vengono memorizzati. Se non si specifica l'inverso = "true" se deve esserci, NH può memorizzare le informazioni ridondanti per due volte.
Se si desidera avere un'associazione unidirezionale vale a dire che i bambini non possono accedere alla Capogruppo. Se è così, colonna FK dovrebbe essere NULLABLE perché i bambini saranno salvati prima che il genitore.