самореферентные отношения с данными весны jpa - PullRequest
0 голосов
/ 06 марта 2019

Я создаю приложение с пружинной загрузкой, и мне нужно установить самореферентные отношения.

Чтобы сделать сценарий простым и понятным, я попытался поработать над аналогичным сценарием на примере объекта отдела.

Ниже приведен сценарий, для которого мне нужно установить самореферентные отношения

  1. Отдел создается со следующими атрибутами - Имя, CostCenter, Местоположение.
  2. Отдел может быть связан с родительским отделом, который также относится к типу
  3. В отделе могут быть подотделы (дочерние), которые также относятся к типу.

Чтобы настроить такой сценарий, я определил сущность Отдел следующим образом.

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

На данный момент я только что попытался связать отдел с другим parentDepartment, как показано в приведенном выше примере, и попытался создать отдел с помощью службы весенней загрузки-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 (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (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"]

Чтобы исправить вышеуказанную проблему, я установил @JsonBackReference в атрибуте «connectedDepartments», после чего операция «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.StackOverflowError

Что я здесь не так делаю?

1 Ответ

1 голос
/ 08 марта 2019

Я попробовал ваш код и до тех пор, пока у вас есть @JsonBackReference для связанных элементов или родительского отдела, он не будет сериализован, что разрешает бесконечную рекурсию.Метод сохранения также работает отлично.Я могу опубликовать код для GitHub для вашей справки.Дайте мне знать.

...