Domanda

non JPA 2 ha alcun meccanismo per l'esecuzione di query ricorsive?

Ecco la mia situazione: ho un'entità E, che contiene un campo intero x. Si può anche avere figli di tipo E, mappato tramite @OneToMany. Quello che mi piacerebbe fare è trovare un E da chiave primaria, e ottenere il suo valore di x, insieme con i valori x di tutti i suoi discendenti. Esiste un modo per fare questo in una singola query?

Sto usando Hibernate 3.5.3, ma preferirei non avere eventuali dipendenze esplicite le API di Hibernate.


EDIT: Secondo questa voce , Hibernate non hanno questa caratteristica, o almeno non ha fatto a marzo. Così sembra improbabile che APP ha voluto che, ma mi piacerebbe fare in modo.

È stato utile?

Soluzione

Utilizzando la semplice adiacenza Modello in cui ogni riga contiene un riferimento ai suoi genitori che farà riferimento ad un'altra riga nella stessa tabella non cooperare bene con JPA. Questo perché JPA non dispone di supporto per la generazione di query utilizzando la clausola di Oracle CONNECT BY o standard SQL CON dichiarazione. Senza uno di questi 2 clausole non è davvero possibile fare l'adiacenza modello utile.

Tuttavia, ci sono un paio di altri approcci alla modellazione questo problema che può applicare a questo problema. Il primo è il materializzato Path Modello . Questo è dove il percorso completo del nodo è appiattita in un'unica 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 solo la colonna 'percorso' un attributo del vostro oggetto persistente. Si dovrà tuttavia fare la contabilità per mantenere il campo 'percorso' fino ad oggi. JPA / Hibernate non farà questo per voi. Per esempio. se si sposta il nodo a un diverso elemento sarà necessario aggiornare sia il genitore di riferimento e determinare il nuovo valore percorso dal nuovo oggetto principale.

L'altro approccio è chiamato il Nested Set Modello , che è po 'più complessa. Probabilmente meglio descritto dal suo creatore (piuttosto che aggiunto alla lettera da me).

C'è un terzo approccio chiamato nidificati Interval modello, tuttavia questo ha una forte dipendenza di stored procedure da attuare.

Una spiegazione molto più completo a questo problema è descritto nel capitolo 7 di noreferrer L'arte di SQL .

Altri suggerimenti

La migliore risposta a questo post sembra un enorme work-around incidere a me. Ho già avuto a che fare con modelli di dati in cui gli ingegneri brillanti deciso che sarebbe una buona idea per il codice Albero Hiarchies nei campi DB come testo come ad esempio: "L'Europa | UK | Shop1 | John" e con grandi volumi di dati in queste tabelle . Non surprsingly, le prestazioni di query forma MyHackedTreeField LIKE 'parentHierharchy%', dove gli assassini. Affrontare questo tipo di problema in definitiva necessaria la creazione di In memoria cache delle hiearchies alberi e tanti altri ...

Se è necessario eseguire una query ricorsive e il volume di dati non è enorme ... rendere la vita semplice e semplicemente caricare campi del DB è necessario eseguire il vostro piano. E codificare il ricorsione in Java. Non farlo nel DB meno che non abbiate una buona ragione per farlo.

E anche se il volume di dati che avete è enorme, è più probabile possibile suddividere il problema in indepent lotti albero ricorsivo ed elaborare quelli uno alla volta, senza bisogno di caricare tutti i dati in una sola volta.

Ho avuto problemi come questo, l'interrogazione di un nodo di menu da una tabella, Il modo in cui ho fondato è stato questo: Supponiamo di avere una classe denominata nodo, ha creato un Unidirectional One-to-Many Associazione in questo modo:

    @OneToMany(  fetch = FetchType.EAGER)
    @JoinColumn(name = "parent_id", referencedColumnName = "id")
    private List<Node> subNodeList;

anche essere un nome depositato per esempio isRoot booleano in entità, parlare se questo nodo è voce del menu principale, e poi, interrogando per i nodi che ci isRoot è vero, otteniamo appena nodi superiore e per FetchType.EAGER, abbiamo anche i nodi secondari nella lista. Questo farà sì che più query, ma per piccolo menu che le cose che sarà ok.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top