I have been writing an endpoint which responds an user information. User
class has id
, name
, and posts
. posts
is list of Post
class, which includes User
so that when I requested the endpoints, the following response returned.
{"id":1,"name":"foo","posts":[{"id":1,"name":"diary","createdAt":null,"user":{"id":1,"name":"foo","posts":...
What I excepted:
{"id": 1, "name": "foo", "posts":[{"id": 1, "name": "diarty", "createdAt": null, "userId": 1}]}
To fix the behaviour, how should I rewrites program?
User.java
@Entity
public class User {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
public Long id;
public String name;
@OneToMany(mappedBy="user", cascade=CascadeType.ALL, orphanRemoval=true)
public List<Post> posts;
}
Post.java
@Entity
public class Post {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
public Long id;
public String name;
public Date createdAt;
@ManyToOne
@JoinColumn(name="user")
public User user;
}
The endpoint:
@GetMapping("/users/{id}")
public User getUserInfo(@PathVariable Long id) {
Optional<User> res = userRepo.findById(id);
if (res.isEmpty()) {
throw new IllegalArgumentException("no user " + id + " found");
} else {
return res.get();
}
}
Use of DTOs will give us control over the expected response.
Create PostDTO
public class PostDTO {
public Long id;
public String name;
public Date createdAt;
public Long userId;
public PostDTO(Post post) {
this.id = post.id;
this.name = post.name;
this.createdAt = post.createdAt;
this.userId = post.user.id;
}
}
Create UserDTO
public class UserDTO {
public Long id;
public String name;
public List<PostDTO> posts;
public UserDTO(User user) {
this.id = user.id;
this.name = user.name;
this.posts = user.posts.stream()
.map(PostDTO::new)
.collect(Collectors.toList());
}
}
Make the required changes in the controller,
@GetMapping("/users/{id}")
public UserDTO getUserInfo(@PathVariable Long id) {
Optional<User> res = userRepo.findById(id);
if (res.isEmpty()) {
throw new IllegalArgumentException("No user " + id + " found");
} else {
return new UserDTO(res.get());
}
}
The above code changes result in the expected JSON response.
Additionally, we can use modelmapper, which simplifies the mapping between entities and DTOs.