錯誤發生的情境如下,一個部門Department
有多個員工Employee
的一對多/多對一關聯。
Employee.java
@Entity
@Table(name="Department")
public class Department {
@id
@Column(name="DepartmentId")
private int departmentId;
@OneToMany(mappedBy="employeeId", cascade={CascadeType.PERSIST, CascadeType.MERGE}) // 串聯新增和更新
private List<Employee> employeeList;
// getter and setter ommitted
}
Department.java
@Entity
@Table(name="Employee")
public class Employee {
@id
@Column(name="EmployeeId")
private int employeeId;
@ManyToOne
@JoinColumn(name="departmentId")
private Department department;
// getter and setter ommitted
}
以上設定在串聯新增Department
及所屬的Employee
時沒有問題,但串聯更新(update)時出現了未知的StackOverflowError
。
最後是透過在@ManyToOne
設定fetch=FetchType.LAZY
解決。
Employee.java
@Entity
@Table(name="Department")
public class Department {
@id
@Column(name="DepartmentId")
private int departmentId;
@OneToMany(mappedBy="employeeId", cascade={CascadeType.PERSIST, CascadeType.MERGE}) // 串聯新增和更新
private List<Employee> employeeList;
// getter and setter ommitted
}
Department.java
@Entity
@Table(name="Employee")
public class Employee {
@id
@Column(name="EmployeeId")
private int employeeId;
@ManyToOne(fetch=FetchType.LAZY) // @ManyToOne JPA預設的fetch=FetchType.EAGER,改為FetchType.LAZY
@JoinColumn(name="departmentId")
private Department department;
// getter and setter ommitted
}
查了一下錯誤原因脫不了無限迴圈的問題,我猜是因為@ManyToOne
預設為FetchType.EAGER
,我的程式在執行時會先查詢Department
物件,因此所屬的Employee
與關聯的Department
(即被查詢的Department
本身)會同時一併取出,而在更新查出的Department
及關聯的Employee
時,Employee
所屬的Department
物件一併被影響,形成無限迴圈而導致StackOverflowError
。
而改為@ManyToOne(fetch=FetchType.LAZY)
,則查詢時Employee
關聯的Department
並未一起取出(只有在存取時才會查詢),所以之後更新查詢出的實體時不會導致無窮迴圈。
另外在網路上找解法時,發現StackOverflowError
錯誤也會出現在當覆寫toString()
方法中彼此呼叫了關聯物件的方法,在查詢時會引發。
沒有留言:
張貼留言