1

Hibernate 5.2.7.Final 및 native Hibernate API를 사용 중입니다. 이제Hibernate 재귀 적 매핑 부모/자식 구조 - 데이터를 가져올 때의 StackOverflowError

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

: 나는 성공적으로 관리자와 직원을 계속

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

: 다음 표는 Hibernate에 의해 생성

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

: 나는 재귀 관계를 가진 직원 엔티티를 직원을 검색하면 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 스택 추적을 포함 할 수 있습니까? 또한 5.2.7에서 재현 할 수 없기 때문에 Hibernate의 어떤 버전을 테스트하고있다. 최종. – Naros

+0

스택 추적을 포함 시켰습니다. 나는 StackOverflowError가 직원 객체가 페치되고, 최대 절전 모드로 관리자를 가져오고, 관리자가 부하 직원 목록에 직원을 가지고있을 때 발생한다고 생각한다. @ManyToOne (fetch = FetchType.LAZY)을 시도했지만 아무 소용이 없습니다. –

답변

1

Employee 엔티티에있는 toString() 메서드에 문제가 있다고 생각됩니다.

코드를 제공하지 않으므로 ParentChild의 좀 더 일반화 된 관점에서 이것이 어떻게 발생하는지 명확한 예가 있습니다.

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

Parent에 호출이 불쾌한주기가 계속 다시 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 + "}"; 
    } 
} 

지금 어딘가에 코드이있다 .

귀하의 경우 가장 논리적 인 의미를 결정하고이 순환 루프를 피하기 위해 연관된 엔티티의 식별자를 건너 뛰거나 인쇄 할 가능성이 높습니다.

+0

당신 말이 맞아요. 나는 그처럼 까다로운 toString()을 가지고있다. 당신의 통찰력에 감사드립니다. –