2013-06-19 2 views
7

У меня есть объекты User и GrantedRole, которые имеют двунаправленное отношение «один ко многим».JPA/Hibernate двунаправленные результаты много-к-одному в StackOverflowException

Когда я пытаюсь добавить GrantedRole к Комплексу в пользователе, то исключение не брошено, но когда я отладка переменных для пользователя и объекта GrantedRole есть описание, которое читает

com.sun.jdi.InvocationException occurred invoking method.

Различных полей поскольку переменные могут быть прочитаны во время отладки, но когда я выбираю поле ролей в User или поле пользователя в GrantedRole, я получаю то же описание, что и выше. Когда я иду в Комплекс GrantedRole в пользователе, я в конечном итоге найти следующее описание:

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

Моего код:

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 
    } 
} 

Это было мое понимание того, что я должен быть в состоянии создать двунаправленный отношение таким образом. Я прочитал несколько руководств, like this one, и я не вижу, что я делаю по-другому, чтобы привести .add (role) к ошибке.

Я отказался от некоторого тривиального кода, если это необходимо, я с радостью предоставил его. Я не сделал код, чтобы гарантировать, что GrantedRole со ссылкой на пользователя ссылается на этого пользователя взамен, но я думаю, что это не относится к проблеме, которую я испытываю.

+0

1. Действительно ли геттеры/сеттеры тривиальны? 2. Полный стек 'StackOverflowError' поможет много понять, что происходит. –

+0

И вы можете добавить код обоих конструкторов 'User (String)' и 'GrantedRole (User, String)', чтобы мы могли точно понять, что вы делаете. – eternay

+2

Это может быть метод рекурсивного вызова 'toString()'. Вы должны убедиться, что вы не вызываете методы, подобные 'equals',' hashCode', ... из дочернего элемента в родительском, только ребенок должен быть заинтересован в вызове от родителя. –

ответ

15

Итак, я просто был глупым и имел рекурсивный вызов в методах toString(). User.toString() попытался напечатать роли, а GrantedRole.toString() попытался напечатать пользователя.

Я исправил его, изменив GrantedRole.toString(), чтобы напечатать user.getUsername(), тем самым нарушив цикл.

+2

То же самое может случиться с вашим методом .hashCode() :) –

+0

спасибо, хороший ответ – FAndrew

+1

Спасибо, застрял с этой проблемой stackoverflow более одного дня для одного-двух двунаправленных. Решена проблема, изменив tostring() –

Смежные вопросы