2016-07-03 4 views
0

두 개의 JPA 엔터티 (작업 및 작업)의 양방향 관계에서 중첩 루프로 인해 Jackson 오류가 발생했습니다. @JsonManagedReference 및 @JsonBackReference 주석을 사용하여이 문제를 해결하기 위해 부분적으로 연구를 시작했지만이 방법은 JSON 직렬화가 내 JobResource/JobResourceAssembler 및 TaskResource/TaskResourceAssembler 위로 점프하는 내 엔티티 내에서 주석을 사용할 때만 작동합니다. HATEOASless 및 HALless json 응답.리소스 및 리소스 어셈블러가있는 Spring HATEOAS/Jackson

내 리소스가이 직렬화/직렬화를 관리 할 수있는 방법이 있습니까?

일부 코드 (내가 JSON 응답을 가지고 있지만 HATEOASless 및 HALless되는 교환에 이런 식으로)

:

@Entity 
public class Task { 

@Id 
@GeneratedValue 
private Long id; 

@OneToMany(mappedBy="task") 
@JsonManagedReference 
private List<Job> job = new ArrayList<Job>(); 

//constructors, getter, setter... 

@Entity 
public class Job { 

@Id 
@GeneratedValue 
private Long id; 

@ManyToOne 
@JsonBackReference 
@JoinColumn(name = "task_id", updatable = true, insertable = true, nullable = true) 
private Task task; 

//constructor, setter, getter. 

HATEOASless 응답 (작업 연결이 있어야합니다)

{ 
"_embedded": { 
"tasks": [ 
    { 
    "name": "Task", 
    "description": "Task Description", 
    "createdAt": 1467583658749, 
    "updatedAt": null, 
    "deletedAt": null, 
    "isActive": true, 
    "estimatedStartDate": null, 
    "startDate": null, 
    "estimatedDateEnd": null, 
    "dateEnd": null, 
    "ids": 1, 
    "risk": null, 
    "job": [ 
     { 
     "id": 2, 
     "name": "Job", 
     "description": "Job Description", 
     "createdAt": 1467583673859, 
     "updatedAt": null, 
     "deletedAt": null, 
     "isActive": true 
     }, 
     { 
     "id": 3, 
     "name": "Job2", 
     "description": "Job Description", 
     "createdAt": 1467583676138, 
     "updatedAt": null, 
     "deletedAt": null, 
     "isActive": true 
     }, 
     { 
     "id": 4, 
     "name": "Job3", 
     "description": "Job Description", 
     "createdAt": 1467583679339, 
     "updatedAt": null, 
     "deletedAt": null, 
     "isActive": true 
     } 
    ], 
    "_links": { 
     "self": { 
     "href": "http://127.0.0.3:7890/api/v1/tasks/1" 
     }, 
     "task": { 
     "href": "http://127.0.0.3:7890/api/v1/tasks/1" 
     } 
    } 
    } 
] 

답변

1

내가 이것을 해결 내 동료. 첫째, 문제는 잭슨이 HATEOAS의 자원을 무시하고 직접 관련 단체를 연재했다는 것입니다. 이것은 우리의 자원이 개체 목록, 아니 자원 목록에 의해 feeded되지 않았기 때문에 발생하는, 그래서 우리는 것으로 변경되었습니다 : 내 자원 목록이 자원이 아닌 일반 기업에 의해 feeded되면서

@Relation(collectionRelation = "tasks") 
public class TaskResource extends ResourceSupport { 

    private List<JobResource> job = new ArrayList<JobResource>(); 

이제, 우리는 서비스를 만들어 목록 작업을 정규 작업으로 채울 수 있습니다.

public List<JobResource> findJobsFromTask(Long id) { 

    Task task = taskRepository.findOne(id); 
    List<Job> jobs = task.getJob(); 
    List<JobResource> jobResourceList = new ArrayList<JobResource>(); 

    for (Job job : jobs) { 
     jobResourceList.add(new JobResourceAssembler().toResource(job)); 
    } 
    return jobResourceList; 
} 

이 갖는, 우리가 그냥 새로운 JobResource를 추가 할 수 있도록 어셈블러를 해결하는 데 필요한 : 엔티티 A는 기본적으로 동일 자신의 자원을 가지고있는 경우이기 때문에, 과정 개발 상당히 빨리

@Override 
public TaskResource toResource(Task task) { 
    taskResource.setJob(taskService.findJobsFromTask(task.getId())); 
} 

그리고 이것은 우리의 해결책이었습니다. 더 좋은 질문이 있으면 의견이나 다른 대답을 남겨주세요.

편집 : 3 개 이상의 중첩 된 리소스가있을 때 수동으로 리소스에 모든 것을 추가해야 할 수 있습니다. 프로젝트 -> 작업 -> 작업이라는 세 가지 리소스가 있습니다. 이전 방법을 사용했다면 중첩 된 Null 오류로 끝날 것입니다. 서비스 :

@Override 
public List<TaskResource> findTaskFromProject(Long id) { 

    Project project = projectRepository.findOne(id); 
    List<Task> tasks = project.getTask(); 
    List<TaskResource> taskResourceList = new ArrayList<TaskResource>(); 

    for (Task task : tasks) { 
     TaskResource taskResource = new TaskResource(); 
     taskResource.setName(task.getName()); 
     taskResource.setDescription(task.getDescription()); 
     taskResource.setCreatedAt(task.getCreatedAt()); 
     taskResource.setUpdatedAt(task.getUpdatedAt()); 
     taskResource.setDeletedAt(task.getDeletedAt()); 
     taskResource.setIsActive(task.getIsActive()); 
     taskResource.setRisk(task.getRisk()); 
     //taskResource.setDocumentState(task.getDocumentState()); 
     taskResource.setEstimatedStartDate(task.getEstimatedStartDate()); 
     taskResource.setStartDate(task.getStartDate()); 
     taskResource.setEstimatedDateEnd(task.getEstimatedDateEnd()); 
     taskResource.setDateEnd(task.getDateEnd()); 
     taskResource.setIds(task.getId()); 
     taskResource.setJob(taskService.findJobsFromTask(task.getId())); 
     taskResource.add(linkTo(TaskController.class).slash("").slash(task.getId()).withSelfRel()); 
     taskResource.add(linkTo(TaskController.class).slash("").slash(task.getId()).withRel("task")); 

     taskResourceList.add(taskResource); 
    } 

    return taskResourceList; 
} 

이렇게하면 프로젝트 -> 작업 -> 작업 JSON 응답 전체 hateoas/hal을 얻을 수 있습니다.