Breve versione per il frettoloso:approccio migliore per il collegamento di diversi tipi di entità in JPA
C'è varie tabelle/entità nel mio modello di dominio che hanno lo stesso campo (un UUID). C'è una tabella in cui ho bisogno di collegare righe/istanze di tali entità ad altre entità gestite da JPA. In altre parole, l'istanza del campo in quella tabella di collegamento non sarà conosciuta in anticipo. I due approcci mi viene in mente sono:
- Utilizzare un'entità astratta e una strategia TABLE_PER_CLASS, o
- utilizzare un
@MappedSuperClass
negozio il nome della classe dell'istanza nella tabella di collegamento pure, o qualcosa di simile che consente Definisco la logica per ottenere l'istanza effettiva dalla tabella giusta.
Entrambi presentano vantaggi e svantaggi in termini di complessità e prestazioni. Quale credi di essere il migliore, c'è forse una terza opzione, o hai provato qualcosa del genere in passato e consiglierei/avvertire fortemente contro?
Versione lunga nel caso in cui si desidera più di fondo:
Ho un modello di database/oggetto in cui molti tipi hanno un campo comune: un identificatore univoco universale (UUID). La ragione di ciò è che le istanze di questi tipi possono essere soggette a modifiche. Le modifiche seguono il modello di comando e i loro dati possono essere incapsulati e se stessi persistono. Chiamiamo un tale cambiamento come una "mutazione". Deve essere possibile scoprire quali mutazioni esistono nel database per ogni data entità, e viceversa, su quale entità opera una mutazione memorizzata.
Prendere le seguenti entità con UUID come esempio (estremamente semplificato):
Per memorizzare le "mutazioni", usiamo un tavolo/un'entità chiamata MutationHolder
. Per collegare una mutazione alla sua entità target, c'è un MutationEntityLink
. L'unica ragione per cui questo dato non è direttamente sul MutationHolder
è perché ci possono essere collegamenti diretti o indiretti, ma questo è di poca importanza qui così ho lasciato fuori:
La questione si riduce a come posso modellare il entity
campo in MutationEntityLink
. Ci sono due approcci a cui riesco a pensare.
Il primo è quello di creare una classe annotata @Entity
con il campo UUID. Customer
, Contract
e Address
lo estenderebbero. Quindi è una strategia TABLE_PER_CLASS. Presumo che potrei usare questo come un tipo per il campo entity
, anche se non ne sono sicuro. Tuttavia, temo che questo potrebbe avere una grave penalizzazione delle prestazioni poiché JPA avrebbe bisogno di interrogare molte tabelle per trovare l'istanza attuale.
Il secondo è utilizzare semplicemente @MappedSuperClass
e memorizzare l'UUID per un'entità nel campo entity
di MutationEntityLink
. Per ottenere l'entità effettiva con quell'UUID, dovrei risolverlo a livello di codice. L'aggiunta di una colonna aggiuntiva con il nome della classe dell'entità, o qualcos'altro che mi consenta di identificarla o di incollarla in una query JPQL, farebbe. Ciò richiede più lavoro ma sembra più efficiente. Non sono contrario alla codifica di alcune classi di utilità o all'effettuazione di alcune annotazioni/annotazioni personalizzate, se necessario.
La mia domanda è quale di questi approcci sembra migliore? In alternativa, potresti avere un suggerimento migliore o notare che mi manca qualcosa; ad esempio, forse c'è un modo per aggiungere una colonna di tipo anche con l'ereditarietà TABLE_PER_CLASS al punto JPA sulla tabella giusta? Forse hai provato qualcosa di simile e vuoi avvertirmi su numerosi problemi che potrebbero sorgere.
Alcune informazioni aggiuntive:
- Creiamo lo schema del database, in modo che possiamo aggiungere tutto ciò che vogliamo.
- Una strategia di ereditarietà a tabella singola non è un'opzione. Le tabelle devono rimanere distinte. Per lo stesso motivo, anche l'ereditarietà unita non sembra una buona idea.
- Il provider JPA è in modalità di sospensione e l'utilizzo di elementi che non fanno parte dello standard JPA non è un problema.
È bello sapere che stai effettivamente utilizzando questo approccio. Mostra che è fattibile. Penso che la sottoclasse di MutationEntityLink per ogni entità mappata sarebbe molto scomoda, quindi una sorta di colonne discriminatorie suona meglio al momento. –
@G_H sì, questo è il motivo per decidere contro le sottoclassi. – Thomas
Mi piace l'idea di @Thomas di creare una sottoclasse di MutationEntityLink per ogni entità. Dal momento che è una classe tecnica che fornisce il collegamento tra le mutazioni e le tue entità, vorrei andare per l'ereditarietà di una singola tabella. La tabella avrebbe la sua colonna discriminatore e una colonna chiave esterna per ogni entità. La tabella potrebbe non essere la rappresentazione più elegante del tuo modello di dominio, ma potresti ottenere buone prestazioni da esso. –