2015-07-08 29 views
6
  • ho viste di un database SQL senza chiave primaria evidenti (composito o in altro modo)
  • vorrei accedervi attraverso JPA

Ho letto che dovrei essere in grado di trattare le viste in JPA come faccio a trattare le tabelle (usando l'annotazione @Table ecc.). Tuttavia senza una chiave primaria devo effettivamente creare una chiave composita da OGNI COLONNA (in effetti, questo in quello che lo strumento di reverse engineering di Hibernate sembra fare di default).Come mappare una vista di database senza una chiave primaria quando si utilizza JPA

Tuttavia, se lo faccio, ci sono effetti collaterali indesiderati. E.g.

  • dover scrivere tutto quello che il codice indica gli attributi della chiave primaria, piuttosto che i punti di vista:.

    myViewObject.getPrimaryKey() getFirstName()

  • Non essendo in grado di utilizzare il "findBy ... "metodi sul repository spring (dato che quell'attributo fa parte dell'identificatore della vista e non in realtà uno dei suoi attributi).

La mia domanda è: Come faccio mappa vista in una tale era come posso facilmente accedere ai loro attributi utilizzando JPA?

Nota: sono abbastanza contento di sentirmi dire che sto usando l'approccio completamente sbagliato. Questo sembra un problema così comune che ci sarà sicuramente una soluzione migliore.

+0

Un trucco che uso è analizzare le query possibili sulla vista per vedere quante hanno il potenziale di restituire più record e vedere se c'è un campo che rimarrà univoco per tutti i record in tutte quelle situazioni. Se riesci a trovare uno scenario di questo tipo, puoi designare quel campo come chiave primaria, anche se non è realmente la chiave primaria poiché l'ORM si preoccupa solo dell'unicità tra i risultati di una singola query. Ma tieni presente che non sarai in grado di utilizzare la cache di secondo livello. Nei casi in cui questo trucco non è applicabile, modifico la query per la vista per includere una chiave primaria. – manish

+0

Non c'è niente che impedisca di scrivere metodi di delega come 'getFirstName()' che restituisce this.getPrimaryKey(). GetFirstName() '. Quindi devi scrivere la versione lunga solo una volta. Per quanto riguarda l'approccio sbagliato, abbiamo oltre 400 Entità/Tabelle nella nostra applicazione e non abbiamo una singola Entità di visualizzazione. Ho provato a utilizzarne una volta perché pensavo che sarebbe stato utile, ma ha iniziato a causare problemi, quindi ho creato la stessa 'vista' in JPQL che ha fatto lo stesso lavoro e mi ha dato maggiore flessibilità. – DuncanKinnear

risposta

5

È possibile aggiungere una colonna UUID a ogni riga delle Viste, quindi è possibile use the UUID column as an @Id.

+0

Sì, ha funzionato, grazie. Ho cambiato la mia vista (Oracle) per includere una colonna aggiuntiva: 'sys_guid() AS uuid' poi aggiunto il seguente proprietà alla parte superiore del mio punto di vista @Entity: ' @Id @Column (name =" UUID ") @JsonIgnore stringa protetta uuidHex;' –

+2

Andy, direi che l'implementazione della soluzione è errata. L'UUID sarà diverso su ogni query. Fondamentalmente è un id valido, ma non mi aspetto di poter selezionare Entity A da un dato UUID più di una volta, cioè. non sarai in grado di navigare da un elenco di entità a una singola entità. Quindi, l'UUID dovrebbe essere parte di una delle tabelle di base e effettivamente memorizzato come una colonna e non calcolato nella vista. Un'alternativa sarebbe l'utilizzo di viste materializzate. –

+0

Al contrario, è esattamente ciò di cui avevo bisogno per risolvere il problema. Il mio problema era che non esisteva una chiave primaria ovvia (vedi sopra). Immagina una raccolta di colonne di dati puri, alcune o tutte null (abbastanza tipico nei database SQL). Ho dovuto dare a ARTIFICI una PK per mantenere felice l'ibernazione. L'aggiunta di un UUID generato alla query ha soddisfatto questi criteri. La navigazione non è mai stata un'opzione in primo luogo. –