2011-10-25 15 views
9

C'è un modo per limitare la dimensione della lista della relazione @OneToMany in JPA? Ecco il mio codice di esempio:@OneToMany limite di dimensione lista di mappatura

@OneToMany(mappedBy = "publication", cascade=CascadeType.PERSIST) 
private List<Comment> commentList; 

sto usando EclipseLink 2.3 implementazione JPA. Grazie in anticipo.

+0

possibile duplicato di [Utilizzo di annotazioni In JPA è possibile limitare i record figlio con una clausola where?] (Http://stackoverflow.com/questions/5857936/using-annotations-in-jpa-can-i-limit-child -records-with-a-where-clausole) –

+0

Questo post vuole limitare quanti elementi sono persistenti, mentre quello collegato vuole recuperare gli elementi che hanno anche altri criteri. Di conseguenza non un "duplicato esatto". – DataNucleus

risposta

12

Parte del Bean Validation Specification (JSR-303) è il @Size(min=, max=) della nota:

tipi supportati sono String, Collection, Mappa e matrici. Controlla se la dimensione dell'elemento annotato è compresa tra min e max (inclusi).

È possibile convalidare la raccolta.

@OneToMany(mappedBy = "publication", cascade=CascadeType.PERSIST) 
@Size(min=1, max=10) 
private List<Comment> commentList; 
2

Non si può fare questo in APP e non ha senso, perché mappature sono stati progettati in modo da riflettere la realtà di quanti oggetti sono nel rapporto.

Stai facendo questo a causa delle prestazioni? Se è così cosa si può fare è quello di utilizzare un pigro recuperare lo stile e utilizzare il BatchSize annotazione specifica quanti si desidera prendere una volta:

* correzione: @Batchsize è una funzionalità di sospensione

@OneToMany(mappedBy = "publication", cascade=CascadeType.PERSIST, fetch=LAZY) 
@BatchSize(size=16) 
private List<Comment> commentList; 

Quindi, nel codice, è sufficiente solo iterare/ripetere il ciclo nel punto desiderato in questa raccolta mappata.

In entrambi i casi, dalla mia esperienza di mapping "hacking" per fare ciò per cui Criterias/Querys sono progettati non è uno sforzo proficuo, quando è necessario un maggiore controllo o ottimizzazione delle prestazioni rispetto a @OneToMany, il modo migliore potrebbe essere solo per fare una query.

+0

Dovrebbe chiarire cosa intendi per "limite", la mia risposta riguarda la simulazione del LIMITE SQL. Se invece vuoi convalidare le dimensioni, usa l'annotazione Dimensione come risposta da @jeha. –

+0

È questo batch da Hibernate? – pringlesinn

+0

Potrebbe essere, io uso entrambi, quindi potrei averli mescolati. :( –

0

Nessun vero modo ortodosso per farlo. Vorrei rendere la relazione pigra, interrogare gli oggetti parent. Dopo le protezioni, non inizializzare l'elenco pigro ed eseguire un'altra query basata sulla prima query, eseguita sulla tabella figlio. In questo modo puoi limitare il set di risultati ai criteri principali e non ai criteri di join. Oppure è possibile eseguire solo la seconda query (solo sulla tabella figlio), con il supporto di paginazione.

2

Il vero problema è la raccolta stessa. Si dovrebbe non modellare il proprio dominio aziendale in questo modo. Questa soluzione (delle raccolte annotate con @OneToMany) è valida solo per le piccole raccolte (dozzine di oggetti) e non per quelle grandi (migliaia di oggetti) che possono benissimo essere il caso dei commenti. Devi davvero stare attento a loro perché possono rapidamente perdere il controllo. Al momento li utilizzo solo per modellare la raccolta di Role s associata a uno Account, perché so che nessun account avrà mai più di 9 ruoli nel mio dominio e perché i ruoli in cui è presente un account sono così molto vitali per funzionare con l'account. Per tutte le altre relazioni m-to-n sto usando semplici vecchie query.

Invece di aggiungere una raccolta di commenti al vostro oggetto, aggiungere un riferimento all'oggetto sul Comment e esplicitamente ottenere i commenti che si desidera utilizzando una query.

definire una query di nome sulla Comment per ottenere i commenti per un certo oggetto (usiamo Article):

@Entity 
@NamedQueries(value={ 
    @NamedQuery(name=Comment.FOR_ARTICLE, query= 
     "SELECT c FROM Comment c WHERE c.article = :article" 
    ) 
}) 
public class Comment { 
    // ... 
    @ManyToOne 
    @JoinColumn(name = "articleId") 
    private Article article; 
} 

Poi, l'uso che prende il nome di query i.c.w. Query.setMaxResults e Query.setFirstResult per controllare in modo esplicito il numero di risultati per ottenere e consentire per il paging, ecc:

@PersistenceContext 
EntityManager em; 

Article theArticle = ...; 

Query query = em.createNamedQuery(Comment.FOR_ARTICLE, Comment.class); 
query.setParameter("article", theArticle); 
query.setFirstResult(0); 
query.setMaxResults(10); 
List<Comment> comments = (List<Comment>) query.getResultList(); 

Per fare di paging, solo setFirstResult al primo risultato corrispondente la pagina che si desidera visualizzare. PER ESEMPIO. per mostrare i risultati 20 .. 29, chiamereste setFirstResult(20).

Problemi correlati