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