2013-06-19 19 views
7

Mam podmioty User i GrantedRole, które mają dwukierunkową relację jeden-do-wielu.Dwustronna konwersja JPA/Hibernacja wiele w jeden powoduje StackOverflowException

Gdy próbuję dodać GrantedRole do zestawu w Użytkownik nie ma wyjątków rzucony, ale kiedy debug zmienne dla użytkownika i obiektu GrantedRole mieć opis, który brzmi

com.sun.jdi.InvocationException occurred invoking method.

różnych dziedzinach ponieważ zmienne można odczytać podczas debugowania, ale gdy wybieram pole ról w polu Użytkownik lub pole użytkownika w GrantedRole, otrzymuję taki sam opis jak powyżej. Kiedy idę do Zestaw GrantedRole na użytkownika, w końcu znaleźć następujący opis:

Detail formatter error: An exception occurred: java.lang.StackOverflowError

Mój kod:

public class User { 
    private Set<GrantedRole> roles = new HashSet<GrantedRole>(); 

    public User() { 
     super(); 
    } 
    public User(String name, String password) { 
     this.name = name; 
     this.password = password; 
    } 

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "user") 
    public Set<GrantedRole> getRoles() { 
     return roles; 
    } 

    public void setRoles(Set<GrantedRole> roles) { 
     this.roles = roles; 
    } 

    // equals and hashCode are based on username 
    // toString is based on all fields 
} 

public class GrantedRole { 
    private user user; 

    public GrantedRole() { 
     super(); 
    } 
    public GrantedRole(User user, Role role, Organization organization) { 
     this.user = user; 
     this.role = role; 
     this.organization = organization; 
    } 

    @ManyToOne 
    @NotNull 
    public User getUser() { 
     return user; 
    } 

    public void setUser(User user) { 
     this.user = user; 
    } 

    // equals and hashCode are based on all fields 
    // toString was based on all fields, I've changed it to not include User. 
} 

public class Test { 
    public void testStuff() { 
     User user = new User("name"); 
     GrantedRole role = new GrantedRole(user, "role"); //this sets the user field 
     user.getRoles().add(role); //doesn't throw Exception, but debugging shows InvocationTargetException and StackOverflowException 
     System.out.println(user.getRoles()); //throws StackOverflowException, as I would expect 
    } 
} 

To było moje zrozumienie, że powinienem być w stanie skonfigurować dwukierunkową związek w ten sposób. Czytam wiele tutoriali, like this one, i nie widzę, co robię inaczej, aby spowodować .add (rolę) pójść źle.

Zostawiłem trochę trywialnego kodu, jeśli jest to potrzebne, chętnie go podam. Nie utworzyłem kodu, aby zapewnić, że dany użytkownik zwróci się do GrantedRole z referencją do użytkownika, ale uważam, że nie ma to znaczenia dla problemu, który mam.

+0

1. Czy gettery/setery są naprawdę trywialne? 2. Pełny stos "StackOverflowError" bardzo pomógłby zrozumieć, co się dzieje. –

+0

Możesz dodać kod obu konstruktorów: 'User (String)' oraz 'GrantedRole (User, String)', abyśmy mogli dokładnie zrozumieć, co dokładnie robisz. – eternay

+2

Może to być wywołanie rekurencyjne metody toString(). Powinieneś się upewnić, że nie wywołasz metod takich jak 'equals',' hashCode', ... od dziecka w rodzicu, tylko dziecko powinno być zainteresowane dzwonieniem od rodzica. –

Odpowiedz

15

Po prostu byłem głupi i miałem rekurencyjne wywołanie w metodach toString(). User.toString() próbował wydrukować role, a GrantedRole.toString() próbował wydrukować użytkownika.

Naprawiłem to, modyfikując GrantedRole.toString(), aby wydrukować user.getUsername(), tym samym przerywając cykl.

+2

to samo może się zdarzyć z metodą .hashCode() :) –

+0

dzięki, dobra odpowiedź – FAndrew

+1

Dzięki, utknął z tym problemem stackoverflow na więcej niż jeden dzień dla jednego do jednego dwukierunkowego.Resolved problem poprzez modyfikowanie tostring() –

Powiązane problemy