2016-03-17 16 views
8

Sto sviluppando un progetto relativamente grande utilizzando Spring Boot e, in generale, sono abbastanza soddisfatto, ma sto riscontrando alcuni problemi nella mia mente non dovrebbe essere un problema.JPA One-To-One pigro e costruzione "dinamica" JSON

  1. Prima di tutto, Relazione One-To-One. È frustrante che non funzioni come dovrebbe (almeno nella mia mente).

    Ho due entità, User e UserProfile, ad esempio. Hanno una relazione One-To-One, ma la maggior parte delle volte ho solo bisogno dei dati User, ma recupera (non importa quello che provo, e oh ragazzo, ho provato i suggerimenti del mondo su ogni post per 5 pagine di Google).

    Quindi c'è la mia prima domanda, c'è un modo per essere in grado di recuperare pigro relazione One-To-One in JPA e Spring? (Perché la maggior parte dei post ha più di 2-3 anni).

  2. L'altro problema che ho è in procinto di costruire una risposta JSON in modo "dinamico". Ho fatto alcune cose usando Rails e sono stato molto contento di JBuilder o anche dello to_json che mi ha dato la possibilità di costruire la risposta JSON a seconda del controller e delle mie esigenze al momento.

    In primavera ho visto le seguenti soluzioni:

    • Jackson @JsonView (che non risolve del tutto il mio problema perché le risposte non sono così statico e un attributo non possono essere assegnati a viste multiple (per quanto riguarda Ho capito il concetto));
    • impostazione su attributi nulli che non voglio sulla risposta (utilizzando questo, ma è troppo brutto e sembra una soluzione sbagliata);
    • o edificio HashMap come io costruisco .json.jbuilder su Rails (ma questo uccide la mia prestazione come a volte ha relazioni così un sacco di for per costruire il json, e anche questo sembra un brutto walkthrough).

Sto cercando alcune direzioni da qualcuno che un giorno potrebbe aver incontrato uno di questi problemi perché è uccidere me non essere in grado in modo da risolvere i problemi che nella mia mente non dovrebbe essere così difficile.

EDIT 1

già tentato di aggiungere optional = false sul @OneToOne annotazioni per risolvere il carico Desideroso di relazione OnetoOne come @snovelli suggerito. Esempio:

@OneToOne(optional=false, fetch = FetchType.LAZY) 
public UserProfile getUserProfile(){ ... } 
+0

La tua domanda contiene due domande non correlate. Dovresti sceglierne uno e estrarre l'altro in una domanda separata. Ad ogni modo, questa è la prima domanda SO in cui ho aggiunto due risposte. :) –

+0

Ci ho pensato, ma ho avuto alcune domande come questa, ma nessuno ha risposto, quindi ho postato questo sapendo che avrei dovuto mettere una taglia in modo che potesse essere risolta, e dato che non ho troppi punti per risparmiare su taglie, ho messo i due in una domanda :(Ma almeno penso che queste siano due domande che potrebbero non avere tutti quelli che non sono maghi a Spring e JPA. – augustoccesar

risposta

6

Se la colonna di join non è nella tabella a cui è associato un genitore in un'associazione uno a uno, quindi l'associazione cannot be lazy. Il motivo è che il provider JPA non è in grado di determinare se creare il proxy, in modo che possa caricare l'oggetto quando si accede successivamente o lasciare il valore null.

Anche se l'associazione non è facoltativa, il provider JPA deve determinare l'id dell'entità dell'entità associata per memorizzarla nel proxy. Quindi deve comunque andare al tavolo associato.

Solutions:

  1. Byte code instrumentation. Approccio non largamente adottato però.
  2. Utilizzare uno-a-molti e gestire l'elenco vuoto come null, altrimenti utilizzare list.get(0). Ovviamente è possibile racchiuderlo nella classe di entità (getter restituisce l'unico elemento della lista o null). Lo svantaggio è che dovrai trattare questo come una raccolta in query JPQL.
  3. Utilizzare @PrimaryKeyJoinColumn anziché una chiave esterna. Se l'associazione non è facoltativa (optional = false), il provider JPA sa che esiste un figlio associato con lo stesso PK, quindi memorizzerà solo il PK del genitore come id del figlio nel proxy. Ovviamente, non è possibile utilizzare due generatori di ID indipendenti per entrambe le entità, altrimenti i PK potrebbero essere diversi. Questo è l'approccio migliore se soddisfa le tue esigenze.
  4. Aggiungere la chiave esterna anche nella tabella padre (rendendo anche la relazione bidirezionale nel database). Lo svantaggio è che ora hai fondamentalmente due associazioni indipendenti che devi mantenere. Inoltre, vi è il costo delle prestazioni dell'aggiornamento di due tabelle anziché di una (e le chiavi esterne devono essere annullabili).
  5. Mappa controllante ad una vista di database che unisce tabella padre con la tabella figlio e contiene tutte le colonne genitore più ID della tabella figlio:

    @OneToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "<child id in the view>", insertable = false, updatable = false) 
    private Child child;
+0

Ha funzionato bene con il terzo suggerimento. il mio tipo Id (il suo detto che sta ricevendo un intero ma mi aspetto un Long) ma dopo aver cambiato il tipo ha funzionato (è qualcosa che cercherò in seguito), l'importante è che ha funzionato. Grazie! – augustoccesar

+0

@augustoccesar Tieni presente che non puoi utilizzare due generatori di ID indipendenti per entrambe le entità con '@ PrimaryKeyJoinColumn', le entità associate devono avere lo stesso PK. –

+0

Dicendo lo stesso PK intendi che sul crono i due stanno usando lo stesso incremento di se un 'User' ha un' id == 1', quindi il relativo 'UserProfile' ha l'id == 1'? – augustoccesar

0

Per quanto riguarda @OneToOne: Sei preoccupato più da quantità di dati o query multiple contro il DB?

Nel primo caso (se possibile quando si utilizza Spring Roo) è possibile provare una soluzione con la modellazione di relazioni @ManyToOne (uno a uno è un caso speciale di molti-a-uno, non è vero).

In quest'ultimo caso è possibile utilizzare @Embeddable per scomporre l'entità come Utente in più classi mantenendo i dati nel DB, quindi verrà utilizzata solo una query per recuperarla.

2

Per quanto riguarda JSON 'dinamica': Usa DTOs.

Questo ha il vantaggio di personalizzare gli oggetti da serializzare in base alle esigenze esatte del client che utilizza il JSON risultante. Inoltre, il modello di dominio (entità Hibernate) è disaccoppiato dalla logica di serializzazione JSON (de), consentendo ai due di evolvere in modo indipendente.

+0

Questo è un ottimo modello! Non lo sapevo. In qualche modo stavo manipolando le risposte, ma usando HashMap. L'uso di DTO sembra più corretto e manutenibile. Grazie! – augustoccesar