I'm now confused about how to do a CRUD in a Rest API with Spring.
Let me explain, I have two routes to POST and PUT an entity. I created two DTOs createPostRequest and updatePostRequest for this. Because when adding, the properties cannot be null, while when updating they can (nulled properties are ignored).
Problem 1:
On my frontend, the user is asked to choose a list of tags from the database (multi select html). This is why createPostRequest has a tags property typed TagDTO. But, how can I use modelMapper to map, for example, the createPostRequest to the Post entity making sure that the tags exist in the database?
if for example a user try to insert a tag that does not exist, I was thinking of doing something like this:
postEntity.setTags(tagService.findAllByIds(postEntity.getTagsId()));
This makes a lot of repetition in the code, because between create and update method of my entity in service, there is a lot of identical code.
Problem 2:
Based on my problem 1, how can I easily map my two DTOs to the same entity without repeating the code 2x?
Code example - PostService (see comment)
This is an example for the update, but there will be almost identical code for the create, so how do I proceed?
@Transactional
public Post update(Integer postId, UpdatePostRequest request) {
return Optional.ofNullable(this.getById(postId)).map(post -> {
// here how to map non-null properties of my request
// into my post taking in consideration my comment above?
postDAO.save(post);
return post;
}).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
}
================================
UPDATE:
As requested, found the code bellow.
The controller:
@RestController
@RequestMapping("/v1/posts")
public class PostController {
RequestMapping(method = RequestMethod.POST, consumes = "application/json", produces = "application/json; charset=UTF-8")
public ResponseEntity<Object> update(@Valid @RequestBody CreatePostRequest createPostRequest) {
Post post = postService.create(createPostRequest);
return new ApiResponseHandler(new PostDTO(post), HttpStatus.OK).response();
}
RequestMapping(value = "/{postId}", method = RequestMethod.PUT, consumes = "application/json", produces = "application/json; charset=UTF-8")
public ResponseEntity<Object> update(@Valid @RequestBody UpdatePostRequest updatePostRequest, @PathVariable Integer postId) {
Post post = postService.update(postId, updatePostRequest);
return new ApiResponseHandler(new PostDTO(post), HttpStatus.OK).response();
}
}
CreatePostRequest :
@Data
public class CreatePostRequest {
@NotNull
@Size(min = 10, max = 30)
private Sting title;
@NotNull
@Size(min = 50, max = 600)
private String description
@NotNull
@ValidDateString
private String expirationDate;
@NotNull
private List<TagDTO> tags;
public List<Integer> getTagIds() {
return this.getTags().stream().map(TagDTO::getId).collect(Collectors.toList());
}
}
UpdatePostRequest :
@Data
public class UpdatePostRequest {
@Size(min = 10, max = 30)
private Sting title;
@Size(min = 50, max = 600)
private String description
@ValidDateString
private String expirationDate;
private List<TagDTO> tags;
public List<Integer> getTagIds() {
return this.getTags().stream().map(TagDTO::getId).collect(Collectors.toList());
}
}
The service :
@Service
@Transactional
public class PostService {
@Transactional
public Post create(CreatePostRequest request) {
ModelMapper modelMapper = new ModelMapper();
Post post = modelMapper.map(request, Post.class);
// map will not work for tags : how to check that tags exists in database ?
return postDAO.save(post);
}
@Transactional
public Post update(Integer postId, UpdatePostRequest request) {
return Optional.ofNullable(this.getById(postId)).map(post -> {
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration().setSkipNullEnabled(true);
modelMapper.map(request, post);
// map will not work for tags : how to check that tags exists in database ?
postDAO.save(post);
return post;
}).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
}
}
0 Comments