2012-07-03 9 views
5

Mam więc tabelę użytkowników, tabelę projektów i tabelę użytkowników. Mam jednego użytkownika, który jest podłączony do 2 projektów, ale kiedy mam tylko jedną rolę dla niego, zwraca te 2 projekty, ale jeśli mam 2 role dla niego, zwraca 4 role (2x2 projekty). Jak mogę zapobiecHibernacja zwraca duplikat, ponieważ inna tabela ma zduplikowane wartości.

To jest mój kod powrocie listę projektów dla użytkownika

@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(); 
} 

mapowania w klasie 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; 
} 

Wszelkie sugestie jaki jest problem?

tnx

Odpowiedz

13

Klasyczny „fix” do spraw zduplikowanych wierszy z kryteriów kwerend, które prawdopodobnie będzie pracować tak długo, jak nie próbujesz połączyć je z numeracją stron, jest dodanie

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 

Wierzę, że dzieje się tak w Twojej sytuacji z powodu szybkiego ładowania ról użytkownika. Zmiana na leniwą może również zadziałać i kontynuować pracę, jeśli potrzebujesz stronicowania.

Ustawienie fetch = FetchType.EAGER nakazuje hibernacji, że zawsze należy załadować wszystkie role dla użytkownika za każdym razem, gdy odzyskasz użytkownika, co osiąga, wykonując zawsze łączenie z tabelą ról.

Niestety, ten SQL prowadzi do wielu rekordów z tym samym użytkownikiem (po jednym dla każdej roli), a następnie musi zostać wyprostowany w Javie po uruchomieniu sql, co robi transformator wyników.

Znacznie bardziej niestety, jeśli chcesz używać stronicowania w najbardziej naturalny sposób z prostych kryteriów hibernacji, używając criteria.setFirstResult i criteria.setMaxResults, rzeczy dzieją się w niewłaściwej kolejności, więc te pytania, które wymagają transformatora wynik uniknąć duplikatów tylko don” t strona po prawej.

Trochę lepiej zrozumieć generowanie sqlacji hibernacji, radzę włączyć rejestrowanie wygenerowanego sql jak opisano w this answer dla innego pytania hibernacji SO.

+1

dziękuję! pracował jak urok, czy możesz jednak wyjaśnić, dlaczego ładowanie ról do tego doprowadzi. Jestem również pewien, że tak jest, ale po prostu nie rozumiem, dlaczego ustawienie czegoś, co nie jest częścią połączenia użytkowników-projektów, powoduje to. jakieś pomysły? –

+0

Zobacz moją aktualizację na nieco więcej na pytanie w komentarzu. –

Powiązane problemy