L'utilizzo del modello di adiacenza dove ogni riga contiene un riferimento ai relativi genitori che farà riferimento a un'altra riga nella stessa tabella non collabora bene con JPA. Questo perché JPA non ha il supporto per la generazione di query utilizzando la clausola Oracle CONNECT BY o l'istruzione SQL standard WITH. Senza una di queste due clausole non è davvero possibile rendere utile il modello di adiacenza.
Tuttavia, ci sono un paio di altri approcci per modellare questo problema che può essere applicato a questo problema. Il primo è il modello di percorso materializzato . È qui che il percorso completo del nodo viene appiattito in una singola colonna. La definizione della tabella si estende in questo modo:
CREATE TABLE node (id INTEGER,
path VARCHAR,
parent_id INTEGER REFERENCES node(id));
Per inserire un albero di nodi sembra qualche cosa come:
INSERT INTO node VALUES (1, '1', NULL); -- Root Node
INSERT INTO node VALUES (2, '1.2', 1); -- 1st Child of '1'
INSERT INTO node VALUES (3, '1.3', 1); -- 2nd Child of '1'
INSERT INTO node VALUES (4, '1.3.4', 3); -- Child of '3'
Quindi, per ottenere Nodo '1' e tutti i suoi figli la query è:
SELECT * FROM node WHERE id = 1 OR path LIKE '1.%';
Per mappare questo a JPA basta rendere la colonna 'percorso' un attributo del proprio oggetto persistente. Dovrai comunque tenere la contabilità per mantenere aggiornato il campo del "percorso". JPA/Hibernate non lo farà per te. Per esempio. se si sposta il nodo su un genitore diverso, sarà necessario aggiornare sia il riferimento principale che il nuovo valore del percorso dal nuovo oggetto principale.
L'altro approccio è denominato nidificato modello di serie, che è un po 'più complesso. Probabilmente il migliore described dal suo creatore (piuttosto che aggiunto per intero da me).
C'è un terzo approccio chiamato Modello intervallo nidificato, tuttavia questo ha un forte affidamento sulle stored procedure da implementare.
Una spiegazione molto più completa di questo problema è descritta nel capitolo 7 di The Art of SQL.
Questo è tutto piuttosto più complesso di quello che stavo cercando, ma grazie per la risposta informativa. C'è anche un'alternativa più semplice al modello di percorso materializzato: ogni nodo memorizza l'ID del nodo radice dell'albero a cui appartiene. Ciò significa che puoi utilizzare il nodo radice solo come punto di partenza della query, ma nel mio caso specifico non è un problema, quindi è probabilmente quello che farò. –
È possibile utilizzare elenchi di adiacenze, gestiti tramite JPA, ma utilizzare una query nativa per utilizzare le funzionalità SQL ricorsive. Sarebbe un po 'icky, e non portatile, ma sarebbe una sorta di migliore dei due mondi. Gli insiemi nidificati sono portatili, ma laboriosi e non si comportano molto bene per alcuni tipi di query abbastanza comuni. –
È cambiato qualcosa con JPA 2.0 ... Ad esempio, ho usato un Native NamedQuery per avere una clausola 'CONNECT BY' nella mia query. L'ho provato e restituisce i bambini, ma non in una lista gerarchica ... Solo bambini piatti. Qualche idea? – SoftwareSavant