1

我使用Hibernate 5.2.7.Final和原生Hibernate API。 我有遞歸關係的僱員實體: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 
} 

下表是由Hibernate創建:

+------------+--------------+------+-----+---------+-------+ 
| 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(); 

異常線程 「main」 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對象圖的方式是如此的方便。但我不知道如何從表中檢索這樣的圖表。

問題:如何從基礎表中有效地檢索員工信息。我認爲它周圍的方法是創建一個新的實體觀看像

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

Employee表我能做到這一點?以及如何使用JPA註釋?

+0

你可以包含StackOverflowError堆棧跟蹤嗎?此外,你測試了什麼版本的Hibernate,因爲我無法在5.2.7.Final上重現這一點。 – Naros

+0

我已經包含了堆棧跟蹤。我認爲StackOverflowError是在獲取員工對象時產生的,hibernate嘗試獲取其管理者,而管理者則在其下屬列表中擁有這樣的員工。我試過@ManyToOne(fetch = FetchType.LAZY),但無濟於事。 –

回答

1

我懷疑問題是您的Employee實體中的toString()方法。

由於您沒有提供任何代碼,下面是一個明確的例子,說明在ParentChild的更廣義視角之間會發生這種情況。

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()。非常感謝你的洞察力。 –