我的问题是我在实体任务和实体用户(作者)之间有一个双向的oneToMany关系。这是在弹簧支架项目中使用弹簧支架和弹簧数据jpa实现的。如果我通过POST-Request创建用户,它可以正常工作。如果我创建一个没有Author(User)实例的Task,则相同。我可以毫无困难地创造它。之后,我尝试通过执行PUT用user-instance更新任务的作者。网络服务的答案是200好的。我在数据库中还有一个条目,在task-table的author列中有用户id。但是当我执行GET-Request来获取所有用户或任务时,任何东西都无法工作。邮差只显示Bad Array等内容。而且我不知道为什么。如果我删除数据库中的任务,一切正常。谁知道为什么? 这里的课程:
@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);
}
}
然后是任务实体:
@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;
}
}
现在任务控制器:
@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;
}
}
}
最后但并非最不重要的是用户控制器:
@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 :(得分:1)
如果您有双向关系,则必须使用@JsonIdentityInfo注释。
让我们看看如何使用@JsonIdentityInfo帮助实现具有双向关系的实体的序列化。
@Entity
@Table(name = "TABLENAME")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class ... {