2009-07-02 13 views
6

Ho un oggetto dell'APP, che ha una relazione molti-a-molti in questo modo:Come utilizzare JPQL per eliminare le voci da una tabella di join?

@Entity 
public class Role { 
    //... 

    @ManyToMany(fetch=FetchType.EAGER) 
    @JoinTable(
    name="RolePrivilege", 
    joinColumns= 
     @JoinColumn(name="role", referencedColumnName="ID"), 
    inverseJoinColumns= 
     @JoinColumn(name="privilege", referencedColumnName="ID") 
    ) 
    private Set<Privilege> privs; 
} 

non c'è un oggetto JPA per RolePrivilege, quindi non sono sicuro di come scrivere una query JPQL da eliminare voci dal campo privs di un oggetto ruolo. Ad esempio, ho provato questo, ma non funziona. Si lamenta che Role.privs non è mappato.

DELETE FROM Role.privs p WHERE p.id=:privId 

non sono sicuro che altro per provare. Naturalmente potrei semplicemente scrivere una query nativa che cancella dalla tabella di join RolePrivilege. Ma sono preoccupato che farlo interagirebbe male con oggetti localmente memorizzati nella cache che non sarebbero stati aggiornati dalla query nativa.

È persino possibile scrivere JPQL per rimuovere le voci da una tabella di join come questa? Altrimenti, posso solo caricare tutti gli oggetti Ruolo e rimuovere le voci dalla collezione privata di ciascuno e quindi conservare ogni ruolo. Ma sembra sciocco farlo se una semplice query JPQL farà tutto in una volta.

risposta

3

Le istruzioni di aggiornamento e cancellazione di JPQL devono fare riferimento a un nome di entità, non a un nome di tabella, quindi penso che tu non abbia fortuna con l'approccio che hai suggerito.

seconda del provider JPA, è possibile eliminare le voci dalla JoinTable utilizzando una semplice istruzione SQL prime (dovrebbe essere portatile 100%) e poi a livello di codice di interagire con il vostro fornitore di cache API di sfrattare i dati. Per esempio in Hibernate è possibile chiamare sfrattare() per scadere tutte le collezioni "Role.privs" dalla cache di 2 ° livello:

sessionFactory.evictCollection("Role.privs", roleId); //evict a particular collection of privs 
sessionFactory.evictCollection("Role.privs"); //evict all privs collections 

Purtroppo io non lavoro con le API JPA abbastanza per sapere con certezza che cosa è esattamente supportato.

2

Java è un linguaggio orientato agli oggetti e l'intero punto di ORM è quello di nascondere i dettagli delle tabelle di join e tali da voi. Di conseguenza, anche la contemplazione dell'eliminazione da un tavolo di join senza considerare le conseguenze sarebbe strana.

No, non è possibile farlo con JPQL, ovvero per le entità.

Recupera le entità alle due estremità e svuota le raccolte. Questo rimuoverà le voci delle tabelle di join. Orientato agli oggetti.

2

Inoltre, stavo cercando un approccio JPQL per eliminare una relazione molti-a-molti (contenuta in una tabella di join). Ovviamente, non c'è alcun concetto di tabella in un ORM, quindi non possiamo usare le operazioni DELETE ... Ma mi piacerebbe che ci fosse un operatore speciale per questi casi. Qualcosa come LINK e UNLINK. Forse una caratteristica futura?

In ogni caso, quello che ho fatto per raggiungere questa esigenza è stato quello di lavorare con le collezioni implementate nei bean di entità, quelle che mappano le relazioni molti-a-molti.

Per esempio, se ho ottenuto uno Studente classe che ha una relazione molti-a-molti relazione con Corsi:

@ManyToMany 
private Collection <Courses> collCourses; 

Costruisco nell'entità un getter e setter per quella collezione. Quindi, ad esempio da un EJB, recupero la raccolta utilizzando il getter, aggiungo o togli il corso desiderato e, infine, utilizzo il setter per assegnare la nuova raccolta. Ed è fatto. Funziona perfettamente.

Tuttavia la mia preoccupazione principale è la prestazione.Un ORM si suppone di mantenere una cache enorme di tutti gli oggetti (se non mi sbaglio), ma anche di utilizzarlo a lavorare più velocemente, mi chiedo se il recupero di tutti ed ogni elemento da una collezione è veramente efficace ...

Perché per me è tanto inefficiente quanto recuperare i registri da una tabella e post-filtrarli usando puro Java invece di un linguaggio di query che funziona direttamente o indirettamente con il motore DB interno (SQL, JPQL ...).

Problemi correlati