与 spring 数据 jpa 的自引用关系
self referencing relationship with spring data jpa
我正在构建一个带有 spring 引导的应用程序,并且必须设置自引用关系。
为了使场景简单易懂,我尝试用一个部门实体示例来处理类似的场景。
以下是我需要建立自引用关系的场景
- 创建的部门具有以下属性 - 名称、成本中心、位置。
- 一个部门可以关联到同样是部门类型的上级部门
- 一个部门可以有同样是部门类型的子部门(子部门)。
为了设置这样的场景,我按以下方式定义了实体 Department。
Department.java
public class Department {
@Id
@GenericGenerator(name = "sequence_department_id", strategy = "com.app.mycompany.AgileCenterServices.util.DepartmentIdGenerator")
@GeneratedValue(generator = "sequence_department_id")
@Column(unique = true)
private String id;
private String name;
private String location;
private String costCenter;
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="parentDepartment")
private Department parentDepartment;
@OneToMany(mappedBy="parentDepartment")
private Set<Department> linkedDepartments = new HashSet<Department>();
/* getters & setters */
}
DepartmentController.java
@CrossOrigin
@RequestMapping(value = "/", method = RequestMethod.POST)
public Department createDepartment(@RequestBody String trial) throws Exception {
logger.info("Inside createDepartment() API ");
ObjectMapper objmapper = new ObjectMapper();
ObjectNode node = objmapper.readValue(trial, ObjectNode.class);
Department deptInput = objmapper.convertValue(node, Department.class);
Department deptRec = null;
/* check if parent department information was passed */
if(deptInput.getParentDepartment() != null) {
Department parentDepartment = departmentRepository.findOne(deptInput.getParentDepartment().getId());
deptInput.setParentDepartment(parentDepartment);
}
try {
logger.info("createDepartment() :: Before save :: Input data ::: " + deptInput.toString());
deptRec = departmentRepository.save(deptInput);
logger.info("createDepartment() :: After save :: Saved successfully ::: " + deptRec.toString());
}
catch (Exception ex) {
ex.printStackTrace();
throw ex;
}
logger.info("Leaving createDepartment() API");
return deptRec;
}
目前,我只是尝试将部门链接到另一个父部门,如上例所示,并尝试使用 spring boot-REST 服务
创建部门
正在正确创建部门。
Saved Department 1 with following input
{"name":"Sales", "costCenter": "SLS", "location":"Global"}
Output:
{
"id": "1000",
"name": "Sales",
"location": "Global",
"costCenter": "SLS",
"parentDepartment": null,
"linkedDepartments": []
}
Saved department 2 with following input
{"name":"Sales-IN", "costCenter": "SLS-IN", "location":"India", "parentDepartment":{"id":"1000"}}
Output:
{
"id": "1001",
"name": "Sales-IN",
"location": "India",
"costCenter": "SLS-IN",
"parentDepartment": {
"id": "1000",
"name": "Sales",
"location": "Global",
"costCenter": "SLS",
"parentDepartment": null,
"linkedDepartments": []
},
"linkedDepartments": []
}
但是,当我现在使用邮递员查询部门中的数据时,我注意到以下异常
@CrossOrigin
@RequestMapping(value="/", method = RequestMethod.GET)
public Page<Department> listDepartments(Pageable pageable) {
logger.info("Inside listDepartments() API");
return departmentRepository.findAll(pageable);
}
异常
2019-03-06 20:04:12.190 WARN 19520 --- [io-8080-exec-10] .m.m.a.ExceptionHandlerExceptionResolver : Resolved exception caused by handler execution: org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (WhosebugError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (WhosebugError) (through reference chain: com.app.mycompany.AgileCenterServices.entities.Department["linkedDepartments"]->org.hibernate.collection.internal.PersistentSet[0]->com.app.mycompany.AgileCenterServices.entities.Department["parentDepartment"]->com.app.mycompany.AgileCenterServices.entities.Department["linkedDepartments"]->org.hibernate.collection.internal.PersistentSet[0]->com.app.mycompany.AgileCenterServices.entities.Department["parentDepartment"]->com.app.mycompany.AgileCenterServices.entities.Department["linkedDepartments"]
为了解决上述问题,我在 "linkedDepartments" 属性上设置了@JsonBackReference,之后 "GET" 操作正常。但保存操作现在失败
2019-03-06 20:19:03.176 WARN 19520 --- [nio-8080-exec-3] .m.m.a.ExceptionHandlerExceptionResolver : Resolved exception caused by handler execution: org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.WhosebugError
我做错了什么?
我试过你的代码,只要你在 linkedDepartments 或 parentDepartment 上有 @JsonBackReference,它就不会被序列化,这解决了无限递归问题。保存方法也可以正常工作。我可以post码成GitHub给大家参考。让我知道。
我正在构建一个带有 spring 引导的应用程序,并且必须设置自引用关系。
为了使场景简单易懂,我尝试用一个部门实体示例来处理类似的场景。
以下是我需要建立自引用关系的场景
- 创建的部门具有以下属性 - 名称、成本中心、位置。
- 一个部门可以关联到同样是部门类型的上级部门
- 一个部门可以有同样是部门类型的子部门(子部门)。
为了设置这样的场景,我按以下方式定义了实体 Department。
Department.java
public class Department {
@Id
@GenericGenerator(name = "sequence_department_id", strategy = "com.app.mycompany.AgileCenterServices.util.DepartmentIdGenerator")
@GeneratedValue(generator = "sequence_department_id")
@Column(unique = true)
private String id;
private String name;
private String location;
private String costCenter;
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="parentDepartment")
private Department parentDepartment;
@OneToMany(mappedBy="parentDepartment")
private Set<Department> linkedDepartments = new HashSet<Department>();
/* getters & setters */
}
DepartmentController.java
@CrossOrigin
@RequestMapping(value = "/", method = RequestMethod.POST)
public Department createDepartment(@RequestBody String trial) throws Exception {
logger.info("Inside createDepartment() API ");
ObjectMapper objmapper = new ObjectMapper();
ObjectNode node = objmapper.readValue(trial, ObjectNode.class);
Department deptInput = objmapper.convertValue(node, Department.class);
Department deptRec = null;
/* check if parent department information was passed */
if(deptInput.getParentDepartment() != null) {
Department parentDepartment = departmentRepository.findOne(deptInput.getParentDepartment().getId());
deptInput.setParentDepartment(parentDepartment);
}
try {
logger.info("createDepartment() :: Before save :: Input data ::: " + deptInput.toString());
deptRec = departmentRepository.save(deptInput);
logger.info("createDepartment() :: After save :: Saved successfully ::: " + deptRec.toString());
}
catch (Exception ex) {
ex.printStackTrace();
throw ex;
}
logger.info("Leaving createDepartment() API");
return deptRec;
}
目前,我只是尝试将部门链接到另一个父部门,如上例所示,并尝试使用 spring boot-REST 服务
创建部门正在正确创建部门。
Saved Department 1 with following input
{"name":"Sales", "costCenter": "SLS", "location":"Global"}
Output:
{
"id": "1000",
"name": "Sales",
"location": "Global",
"costCenter": "SLS",
"parentDepartment": null,
"linkedDepartments": []
}
Saved department 2 with following input
{"name":"Sales-IN", "costCenter": "SLS-IN", "location":"India", "parentDepartment":{"id":"1000"}}
Output:
{
"id": "1001",
"name": "Sales-IN",
"location": "India",
"costCenter": "SLS-IN",
"parentDepartment": {
"id": "1000",
"name": "Sales",
"location": "Global",
"costCenter": "SLS",
"parentDepartment": null,
"linkedDepartments": []
},
"linkedDepartments": []
}
但是,当我现在使用邮递员查询部门中的数据时,我注意到以下异常
@CrossOrigin
@RequestMapping(value="/", method = RequestMethod.GET)
public Page<Department> listDepartments(Pageable pageable) {
logger.info("Inside listDepartments() API");
return departmentRepository.findAll(pageable);
}
异常
2019-03-06 20:04:12.190 WARN 19520 --- [io-8080-exec-10] .m.m.a.ExceptionHandlerExceptionResolver : Resolved exception caused by handler execution: org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (WhosebugError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (WhosebugError) (through reference chain: com.app.mycompany.AgileCenterServices.entities.Department["linkedDepartments"]->org.hibernate.collection.internal.PersistentSet[0]->com.app.mycompany.AgileCenterServices.entities.Department["parentDepartment"]->com.app.mycompany.AgileCenterServices.entities.Department["linkedDepartments"]->org.hibernate.collection.internal.PersistentSet[0]->com.app.mycompany.AgileCenterServices.entities.Department["parentDepartment"]->com.app.mycompany.AgileCenterServices.entities.Department["linkedDepartments"]
为了解决上述问题,我在 "linkedDepartments" 属性上设置了@JsonBackReference,之后 "GET" 操作正常。但保存操作现在失败
2019-03-06 20:19:03.176 WARN 19520 --- [nio-8080-exec-3] .m.m.a.ExceptionHandlerExceptionResolver : Resolved exception caused by handler execution: org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.WhosebugError
我做错了什么?
我试过你的代码,只要你在 linkedDepartments 或 parentDepartment 上有 @JsonBackReference,它就不会被序列化,这解决了无限递归问题。保存方法也可以正常工作。我可以post码成GitHub给大家参考。让我知道。