2012-07-03 10 views
5

Quindi ho una tabella utenti, tabella progetti e tabella User_Roles. Ho un utente connesso a 2 progetti, ma quando ho un solo ruolo per lui restituisce quei 2 progetti, ma se ho 2 ruoli per lui restituisce 4 ruoli (progetti 2x2). Come posso evitare questoHibernate restituisce duplicato perché un'altra tabella ha valori duplicati

Questo è il mio codice per la restituzione l'elenco dei progetti per l'utente

@Override 
public List<Project> retrieve(User user) { 
    Criteria criteria = super.createCriteria(); 
    criteria.addOrder(Order.desc("date")); 
    criteria.createCriteria("users").add(Restrictions.eq("id", user.getId())); 

    return (List<Project>) criteria.list(); 
} 

mappature in classe User

@ManyToMany(cascade = CascadeType.ALL) 
@JoinTable(name = "Users_Projects", 
      joinColumns = @JoinColumn(name = "UserID"), inverseJoinColumns = @JoinColumn(name = "ProjectID")) 
public List<Project> getProjects() { 
    return projects; 
} 

@ElementCollection(fetch = FetchType.EAGER) 
@Enumerated(EnumType.STRING) 
@Column(name = "RoleType") 
@JoinTable(name = "User_Roles", joinColumns = @JoinColumn(name = "UserID")) 
public Set<Role> getRoles() { 
    return roles; 
} 

Qualche suggerimento qual è il problema?

TNX

risposta

13

Il classico "fix" per le questioni di righe duplicate da criteri di query, che probabilmente funzionerà fino a quando non si sta cercando di combinarlo con impaginazione, è quello di aggiungere

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 

Credo che questo stia accadendo nella tua situazione a causa del carico impetuoso dei ruoli degli utenti. Cambiare quello per essere pigro potrebbe anche funzionare, e continuare a lavorare se hai bisogno di impaginazione.

L'impostazione fetch = FetchType.EAGER indica a ibernazione che si desidera caricare sempre tutti i ruoli per l'utente ogni volta che si recupera un utente, operazione che viene eseguita eseguendo sempre un join nella tabella dei ruoli.

Sfortunatamente, che SQL porta a più record con lo stesso utente (uno per ciascun ruolo), e quindi deve essere raddrizzato in Java dopo l'esecuzione di SQL, che è ciò che fa il trasformatore di risultati.

Molto di più, purtroppo, se si desidera utilizzare il paging nel modo più naturale con semplici criteri di Hibernate, utilizzando criteria.setFirstResult e criteria.setMaxResults, le cose accadono in ordine errato, in modo da queste query che necessitano il trasformatore risultato per evitare duplicati appena don' t pagina destra.

Per comprendere meglio un po 'meglio la generazione di SQL di ibernazione, suggerirei di attivare la registrazione dello sql generato come descritto in this answer in un'altra domanda SO di sospensione.

+1

grazie! ha funzionato come un incantesimo, puoi comunque spiegare perché il caricamento dei ruoli potrebbe portare a questo. Sono anche sicuro che sia così, ma non seguo il motivo per cui l'impostazione di qualcosa che non fa parte della connessione dei progetti utente lo fa. qualche idea? –

+0

Vedere il mio aggiornamento per un po 'di più sulla domanda nel tuo commento. –

Problemi correlati