2016-06-23 2 views
1

Mein Problem ist, dass ich eine bidirektionale oneToMany Beziehung zwischen einer Entität Aufgabe und einem Entität Benutzer (Autor) habe. Dies wird in einem Spring-Boot-Projekt mit Federauflage und Federdaten jpa realisiert. Wenn ich einen Benutzer durch eine POST-Anfrage erstelle, funktioniert es gut. Dasselbe gilt, wenn ich eine Aufgabe ohne Autor (User) -Instanz erstelle. Ich kann es ohne Probleme schaffen. Danach versuche ich den Autor der Aufgabe mit einer Benutzerinstanz zu aktualisieren, indem ich PUT ausführe. Die Antwort des Webservice ist 200 Okay. Ich habe auch einen Eintrag in der Datenbank mit der Benutzer-ID in der Autor-Spalte der Aufgabentabelle. Aber wenn ich eine GET-Anfrage für alle Benutzer oder Aufgaben ausführen, funktioniert nichts mehr. Postbote zeigt nur Dinge wie Bad Array an. Und ich habe keine Ahnung warum. Wenn ich die Aufgabe in der Datenbank lösche, funktioniert alles wieder gut. Hat jemand eine Idee warum? Hier werden die Klassen:Aktualisierung einer OneToMany Beziehung mit Spring REST

@Entity 
@Table(name="User") 
public class User { 
@Id 
@GeneratedValue 
@Column(name="USER_ID") 
private Long id; 

@Column(name="CONFIRMATION") 
private boolean confirmed; 

@Column(name = "EMAIL",nullable = false) 
private String email; 

@Column(name = "USERNAME",nullable = false) 
@NotNull 
private String userName; 

@Column(name="PASSWORD",nullable = false) 
@NotNull 
private String password; 

@Column(name="TIMESTAMP") 
private Long creationTime; 

@OneToMany(cascade=CascadeType.ALL, mappedBy="author",fetch=FetchType.EAGER) 
private Set<Task>assignedTasks; 

@OneToMany(cascade=CascadeType.ALL, mappedBy="assignee",fetch=FetchType.EAGER) 
private Set<Task>createdTasks; 


public User() { 
} 

public Long getId() { 
    return id; 
} 

public void setId(Long id) { 
    this.id = id; 
} 



public String getEmail() { 
    return email; 
} 

public void setEmail(String email) { 
    this.email = email; 
} 

public String getUserName() { 
    return userName; 
} 

public void setUserName(String userName) { 
    this.userName = userName; 
} 

public String getPassword() { 
    return password; 
} 

public void setPassword(String password) { 
    this.password = password; 
} 

public Long getCreationTime() { 
    return creationTime; 
} 

public void setCreationTime(Long creationTime) { 
    this.creationTime = creationTime; 
} 

public boolean isConfirmed() { 
    return confirmed; 
} 

public void setConfirmed(boolean confirmed) { 
    this.confirmed = confirmed; 
} 

public Set<Task> getAssignedTasks() { 
    return assignedTasks; 
} 

public void setAssignedTasks(Set<Task> assignedTasks) { 
    this.assignedTasks = assignedTasks; 
} 

public void addAssignedTasks(Task task){ 
    addAssignedTasks(task,true); 
} 

void addAssignedTasks(Task task, boolean set){ 
    if(task != null){ 
     getAssignedTasks().add(task); 
     if(set){ 
      task.setAssignee(this); 
     } 
    } 
} 

public Set<Task> getCreatedTasks() { 
    return createdTasks; 
} 

public void setCreatedTasks(Set<Task> createdTasks) { 
    this.createdTasks = createdTasks; 
} 

public void addCreatedTask(Task task){ 
    addCreatedTask(task,true); 
} 

void addCreatedTask(Task task, boolean set){ 
    if(task != null){ 
     getCreatedTasks().add(task); 
     if(set){ 
      task.setAuthor(this); 
     } 
    } 
} 

public void removeCreatedTask(Task task) { 
    getCreatedTasks().remove(task); 
    task.setAuthor(null); 
} 

}

die Aufgabe Entity Dann:

@Entity 
@Table(name="Task") 
public class Task { 


@Id 
@GeneratedValue 
@Column(name="TASK_ID") 
private Long id; 

@Transient 
private List<String> possibleTaskTypes = TaskType.getTaskTypesAsString(); 

@Transient 
private List<String>possibleTaskContainer = TaskContainer.getTaskContainerAsString(); 

@Column(name="TASK_Container") 
private String taskContainer; 

@Column(name="TASK_TYPE") 
private String taskType; 

@Column(name="HEAD_LINE") 
private String headLine; 

@Column(name="TASK_TEXT") 
private String taskText; 

@Transient 
private List<String> possibleworkFlowStati = WorkFlowStatus.getWorkFlowsStatiAsString(); 

@Column(name="WORKFLOW_STATUS") 
private String status; 

@ManyToOne(cascade=CascadeType.ALL) 
private User author; 

@ManyToOne(cascade=CascadeType.ALL) 
private User assignee; 

@Column(name="COMMENTS") 
@ElementCollection(targetClass=String.class) 
private List<String>comments; 

@ManyToOne(cascade=CascadeType.ALL) 
private Sprint sprint; 

@Column(name="TIMESTAMP") 
private Long creationTime; 

public Long getId() { 
    return id; 
} 

public void setId(Long id) { 
    this.id = id; 
} 

public String getHeadLine() { 
    return headLine; 
} 

public void setHeadLine(String headLine) { 
    this.headLine = headLine; 
} 

public String getTaskText() { 
    return taskText; 
} 

public void setTaskText(String taskText) { 
    this.taskText = taskText; 
} 

public User getAuthor() { 
    return author; 
} 

public void setAuthor(User author) { 
    setAuthor(author, true); 
} 

void setAuthor(User author, boolean add){ 
    this.author = author; 
    if(author !=null&&add){ 
     author.addCreatedTask(this, false); 
    } 
} 

public User getAssignee() { 
    return assignee; 
} 

public void setAssignee(User assignee) { 
    setAssignee(assignee,true); 
} 

void setAssignee(User assignee, boolean add){ 
    this.assignee = assignee; 
    if(assignee != null && add){ 
     assignee.addAssignedTasks(this,false); 
    } 
} 

public List<String> getComments() { 
    return comments; 
} 

public void setComments(List<String> comments) { 
    this.comments = comments; 
} 

public Sprint getSprint() { 
    return sprint; 
} 

public void setSprint(Sprint sprint) { 
    this.sprint = sprint; 
} 

public Long getCreationTime() { 
    return creationTime; 
} 

public void setCreationTime(Long creationTime) { 
    this.creationTime = creationTime; 
} 

public String getTaskType() { 
    return taskType; 
} 

public void setTaskType(String taskType) { 
    this.taskType = taskType; 
} 

public List<String> getPossibleTaskTypes() { 
    return possibleTaskTypes; 
} 

public void setPossibleTaskTypes(List<String> possibleTaskTypes) { 
    this.possibleTaskTypes = possibleTaskTypes; 
} 

public List<String> getPossibleworkFlowStati() { 
    return possibleworkFlowStati; 
} 

public void setPossibleworkFlowStati(List<String> possibleworkFlowStati) { 
    this.possibleworkFlowStati = possibleworkFlowStati; 
} 

public String getStatus() { 
    return status; 
} 

public void setStatus(String status) { 
    this.status = status; 
} 

public List<String> getPossibleTaskContainer() { 
    return possibleTaskContainer; 
} 

public void setPossibleTaskContainer(List<String> possibleTaskContainer) { 
    this.possibleTaskContainer = possibleTaskContainer; 
} 

public String getTaskContainer() { 
    return taskContainer; 
} 

public void setTaskContainer(String taskContainer) { 
    this.taskContainer = taskContainer; 
} 




} 

nun die Aufgabe-Controller:

@RestController 
@RequestMapping("/v1/") 
@Api(value = "tasks", description = "V1 - Tasks API") 
public class TaskController { 

private final Logger logger = LoggerFactory.getLogger(TaskController.class); 
private TaskRepository taskRepository; 
private UserRepository userRepository; 

@Autowired 
public TaskController(TaskRepository taskRepository, UserRepository userRepository){ 
    this.taskRepository = taskRepository; 
    this.userRepository = userRepository; 

} 

protected void verifyTaskById(Long id) throws ResourceNotFoundException{ 
    Task task = taskRepository.findOne(id); 
    if(task == null){ 
     throw new ResourceNotFoundException("Task with ID:"+id+" not found."); 
    } 
} 
/** 
* <b>POST</b> v1/tasks/ 
* @param task 
* @return 
*/ 
@RequestMapping(value="tasks", method=RequestMethod.POST) 
@ApiOperation(value = "Creates a new Task", notes="The newly created Task Id will be sent in the location response header", 
response = Void.class) 
@ApiResponses(value = {@ApiResponse(code=201, message="Task Created Successfully", response=Void.class), @ApiResponse(code=500, message="Error creating Task", response=ErrorDetail.class) }) 
public ResponseEntity<?> createTask(@Valid @RequestBody Task task){ 
    logger.info(task.toString()); 
    task.setCreationTime(new Date().getTime()); 

    task = taskRepository.save(task); 
    HttpHeaders responseHeaders = new HttpHeaders(); 

    URI newTaskUri = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(task.getId()).toUri(); 
    responseHeaders.setLocation(newTaskUri); 

    return new ResponseEntity<>(null, responseHeaders, HttpStatus.CREATED); 
} 

/** 
* <b>GET</b> v1/tasks/ 
* @return 
*/ 
@RequestMapping(value = "tasks", method = RequestMethod.GET) 
@ApiOperation(value = "Retrieves all the tasks", response=Task.class, responseContainer="List") 
public ResponseEntity<Page<Task>> listAllTasks(Pageable pageable){ 
    logger.info("Receiving get-Tasks Request.."); 
    Page<Task> allTasks = taskRepository.findAll(pageable); 
    return new ResponseEntity<>(allTasks,HttpStatus.OK); 
} 

/** 
* <b>GET</b> v1/tasks/{id} 
* @param id 
* @return 
*/ 
@RequestMapping(value = "tasks/{id}", method = RequestMethod.GET) 
@ApiOperation(value = "Retrieves given Task", response=Task.class) 
@ApiResponses(value = {@ApiResponse(code=200, message="", response=Task.class), @ApiResponse(code=404, message="Unable to find Task", response=ErrorDetail.class) }) 
public ResponseEntity<?> getSingleTask(@PathVariable(value="id") Long id){ 
    logger.info("Receiving get Task-Request for ID: "+ id); 
    verifyTaskById(id); 
    Task task = taskRepository.findOne(id); 
    return new ResponseEntity<>(task,HttpStatus.OK); 
} 

/** 
* <b>PUT</b> v1/tasks/{id} 
* @param task 
* @param id 
* @return 
*/ 
@RequestMapping(value = "tasks/{id}", method = RequestMethod.PUT) 
@ApiOperation(value = "Updates given Task", response=Void.class) 
@ApiResponses(value = {@ApiResponse(code=200, message="", response=Void.class), 
     @ApiResponse(code=404, message="Unable to find Task", response=ErrorDetail.class) }) 
public ResponseEntity<?> updateTask(@RequestBody Task task, @PathVariable(value="id") Long id) { 
    logger.info("Receiving put Task Request for "+id); 
    verifyTaskById(id); 
    if(!isIdInBodyCorrect(task, id)){ 
     task.setId(id); 
    } 

    if(task.getAuthor() != null)userRepository.save(task.getAuthor()); 
    if(task.getAssignee()!=null)userRepository.save(task.getAssignee()); 
    Task t = taskRepository.save(task); 

    return new ResponseEntity<>(HttpStatus.OK); 
} 

/** 
* <b>DELETE</b> v1/tasks/{id} 
* 
* @param id 
* @return 
*/ 
@RequestMapping(value = "tasks/{id}", method = RequestMethod.DELETE) 
@ApiOperation(value = "Deletes given Task", response=Void.class) 
@ApiResponses(value = {@ApiResponse(code=200, message="", response=Void.class), 
     @ApiResponse(code=404, message="Unable to find Task", response=ErrorDetail.class) }) 
public ResponseEntity<?> deleteTask(@PathVariable (value="id") Long id) { 
    verifyTaskById(id); 
    taskRepository.delete(id); 
    return new ResponseEntity<>(HttpStatus.OK); 
} 

protected boolean isIdInBodyCorrect(Task task, Long id){ 
    if(task.getId() != id){ 
     logger.warn("Id in Body wasn't defined or wrong. "); //TODO Exception werfen. 
     return false; 
    }else{ 
     return true; 
    } 
} 

} 

Und schließlich der Nutzer-Controller nicht zuletzt :

@RestController 
@RequestMapping("/v1/") 
@Api(value = "users", description = "V1 - Users API") 
public class UserController { 

private final Logger logger = LoggerFactory.getLogger(UserController.class); 

private UserRepository userRepository; 

@Autowired 
public UserController(UserRepository userRepository){ 
    this.userRepository = userRepository; 
} 
/** 
* Checks wether the user exists. If not it throws a {@link ResourceNotFoundException}. 
* @param id 
* @throws ResourceNotFoundException 
*/ 
protected void verifyUserById(Long id) throws ResourceNotFoundException{ 
    User user = userRepository.findOne(id); 
    if(user==null){ 
     throw new ResourceNotFoundException("User with ID:"+id+" not found."); 
    } 
} 
/** 
* <b>POST</b> v1/users/ 
* @param user 
* @return 
*/ 
@RequestMapping(value="users", method=RequestMethod.POST) 
@ApiOperation(value = "Creates a new User", notes="The newly created user Id will be sent in the location response header", 
response = Void.class) 
@ApiResponses(value = {@ApiResponse(code=201, message="User Created Successfully", response=Void.class), @ApiResponse(code=500, message="Error creating User", response=ErrorDetail.class) }) 
public ResponseEntity<?> createUser(@Valid @RequestBody User user) { 
    user.setCreationTime(new Date().getTime()); 
    user = userRepository.save(user); 

    // Set the location header for the newly created resource 
    HttpHeaders responseHeaders = new HttpHeaders(); 
    URI newUserUri = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(user.getId()).toUri(); 
    responseHeaders.setLocation(newUserUri); 

    return new ResponseEntity<>(null, responseHeaders, HttpStatus.CREATED); 
} 
/** 
* <b>GET</b> v1/users/ 
* @return 
*/ 
@RequestMapping(value = "users", method = RequestMethod.GET) 
@ApiOperation(value = "Retrieves all the users", response=User.class, responseContainer="List") 
public ResponseEntity<Page<User>> listAllUsers(Pageable pageable){ 
    Page<User> allUsers = userRepository.findAll(pageable); 
    return new ResponseEntity<>(allUsers,HttpStatus.OK); 
} 

/** 
* <b>GET</b> v1/users/{id} 
* @param id 
* @return 
*/ 
@RequestMapping(value = "users/{id}", method = RequestMethod.GET) 
@ApiOperation(value = "Retrieves given User", response=User.class) 
@ApiResponses(value = {@ApiResponse(code=200, message="", response=User.class), @ApiResponse(code=404, message="Unable to find User", response=ErrorDetail.class) }) 
public ResponseEntity<?> getSingleUser(@PathVariable(value="id") Long id){ 
    verifyUserById(id); 
    User user = userRepository.findOne(id); 
    return new ResponseEntity<>(user,HttpStatus.OK); 
} 
/** 
* <b>PUT</b> v1/users/{id} 
* @param user 
* @param id 
* @return 
*/ 
@RequestMapping(value = "users/{id}", method = RequestMethod.PUT) 
@ApiOperation(value = "Updates given User", response=Void.class) 
@ApiResponses(value = {@ApiResponse(code=200, message="", response=Void.class), 
     @ApiResponse(code=404, message="Unable to find User", response=ErrorDetail.class) }) 
public ResponseEntity<?> updateUser(@RequestBody User user, @PathVariable (value="id") Long id) { 
    verifyUserById(id); 
    // Save the entity 
    if(!isIdInBodyCorrect(user,id)){ 
     user.setId(id); 
    } 
    User u = userRepository.findOne(id); 
    userRepository.save(user); 
    return new ResponseEntity<>(HttpStatus.OK); 
} 

/** 
* <b>DELETE</b> v1/users/{id} 
* @param id 
* @return 
*/ 
@RequestMapping(value="users/{id}", method=RequestMethod.DELETE) 
@ApiOperation(value = "Deletes given User", response=Void.class) 
@ApiResponses(value = {@ApiResponse(code=200, message="", response=Void.class), 
     @ApiResponse(code=404, message="Unable to find User", response=ErrorDetail.class) }) 
public ResponseEntity<?> deleteUser(@PathVariable (value="id") Long id) { 
    verifyUserById(id); 
    userRepository.delete(id); 
    return new ResponseEntity<>(HttpStatus.OK); 
} 

protected boolean isIdInBodyCorrect(User user, Long id){ 
    if(user.getId() != id){ 
     logger.warn("Id in Body wasn't defined or wrong. "); //TODO Exception werfen. 
     return false; 
    }else{ 
     return true; 
    } 
} 



} 
+0

Ich würde sagen, post die "Fehler" Antwort, die Sie bekommen. Das hilft, das Problem besser zu erkennen –

Antwort

1

Wenn Sie eine bidirektionale Beziehung haben, müssen Sie @JsonIdentityInfo Annotation verwenden.

Lassen Sie uns sehen, wie Sie mit der Serialisierung von Elementen mit bidirektionaler Beziehung mit @JsonIdentityInfo helfen können.

@Entity 
@Table(name = "TABLENAME") 
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") 
public class ... { 
Verwandte Themen