1

Я использую Hibernate 5.2.7.Final и собственный Hibernate API. У меня есть объект Employee с рекурсивными отношениями:Рекурсивное отображение родительской/дочерней структуры Hibernate - StackOverflowError при извлечении данных

@Entity 
public class Employee { 

    @Id 
    @GeneratedValue 
    private Long employeeId; 

    @Column 
    private String firstname; 

    @Column 
    private String lastname; 

    @ManyToOne(cascade={ CascadeType.ALL}) 
    @JoinColumn(name="manager_id") 
    private Employee manager; 

    @OneToMany(mappedBy="manager", cascade = CascadeType.ALL) 
    private Set<Employee> subordinates = new HashSet<Employee>(); 
    // setters, getters, constructors 
} 

Следующая таблица создается с помощью спящего режима:

+------------+--------------+------+-----+---------+-------+ 
| Field  | Type   | Null | Key | Default | Extra | 
+------------+--------------+------+-----+---------+-------+ 
| employeeId | bigint(20) | NO | PRI | NULL |  | 
| firstname | varchar(255) | YES |  | NULL |  | 
| lastname | varchar(255) | YES |  | NULL |  | 
| manager_id | bigint(20) | YES | MUL | NULL |  | 
+------------+--------------+------+-----+---------+-------+ 

Я успешно упорствую менеджер и сотрудник с:

Employee manager = new Employee("A", "B"); 

    Employee employee1 = new Employee("C", "D"); 
    Employee employee2 = new Employee("E", "E"); 

    employee1.setManager(manager1); 
    employee2.setManager(manager1); 

    Set<Employee> employees = new HashSet<>(); 
    employees.add(employee1); 
    employees.add(employee2); 

    manager.setSubordinates(employees); 

    session.save(manager); 

сейчас извлечение сотрудника вызовет StackOverFlowError.

Long id = manager.getEmployeeId(); 

    Query<Employee> query = ss.createQuery("from Employee e where e.employeeId = :employeeId", Employee.class); 

    query.setParameter("employeeId", id); 

    Employee retrieved = (Employee) query.uniqueResult(); 

Исключение в потоке «главный» java.lang.StackOverflowError

at java.lang.Long.toString(Long.java:396) 
at java.lang.Long.toString(Long.java:1032) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 
at java.lang.StringBuilder.append(StringBuilder.java:131) 
at objectModels.Employee.toString(Employee.java:82) 
at java.lang.String.valueOf(String.java:2994) 

Я думаю, как я могу оставаться такой объект Employee график так удобно. Но я не знаю, как извлечь такой график из таблицы.

Вопрос: Как я могу осмысленно извлекать информацию о сотрудниках из базовой таблицы. Я думаю, что путь вокруг него, чтобы создать новый объект для просмотра таблицы Employee как

public class EmployeeView { 
      private Long employeeId; 
      private String firstname; 
      private String manager_name; 
      private Set<String> subordinate_names; 
    } 

Могу ли я этого добиться? и как с аннотацией JPA?

+0

Можете выложить трассировку стека 'StackOverflowError'? Кроме того, какую версию Hibernate вы тестируете, так как я не могу воспроизвести это на 5.2.7.Final. – Naros

+0

Я включил трассировку стека. Я думаю, что StackOverflowError вызывается, когда объект-сотрудник загружается, hibernate пытается получить своих менеджеров, а менеджер, в свою очередь, имеет такого сотрудника в списке подчиненных. Я пробовал @ManyToOne (fetch = FetchType.LAZY), но безрезультатно. –

ответ

1

Я подозреваю, что проблема заключается в методе toString() в вашем объекте Employee.

Поскольку вы не указали какой-либо код, вот ясный пример того, как это произойдет между более обобщенной перспективой Parent и Child.

public class Parent { 
    @OneToMany(mappedBy = "parent"); 
    List<Child> children; 

    @Override 
    public String toString() { 
    StringBuilder sb = new StringBuilder(); 
    sb.append("Parent{children="); 
    children.forEach(sb::apend); 
    sb.append("}"); 
    return sb.toString(); 
} 

public class Child { 
    @ManyToOne 
    private Parent parent; 

    @Override 
    public String toString() { 
    return "Child{parent=" + parent + "}"; 
    } 
} 

Сейчас где-то в коде есть это:

System.out.println(parent.toString()); 

Это вызовет такую ​​же проблему переполнения, потому что вызов в Parent бы делегировать вниз в Child который делегирует назад Parent и неприятный цикл продолжается ,

Вам необходимо решить, какой из них наиболее логичен в вашем случае и, вероятно, либо пропустить, либо распечатать только идентификатор связанного объекта, чтобы избежать этого рекурсивного цикла.

+0

Вы правы. У меня такая неприятная toString(). Большое вам спасибо за понимание. –