【发布时间】:2021-11-16 19:54:58
【问题描述】:
我现在对如何使用 Spring 在 Rest API 中执行 CRUD 感到困惑。
让我解释一下,我有两条路线来 POST 和 PUT 一个实体。为此,我创建了两个 DTO createPostRequest 和 updatePostRequest。因为添加的时候属性不能为空,更新的时候可以(忽略为空的属性)。
问题一:
在我的前端,用户被要求从数据库中选择一个标签列表(多选 html)。这就是为什么createPostRequest 有一个tags 属性类型为TagDTO。但是,如何使用 modelMapper 将 createPostRequest 映射到 Post 实体以确保标签存在于数据库中?
例如,如果用户尝试插入不存在的标签,我正在考虑这样做:
postEntity.setTags(tagService.findAllByIds(postEntity.getTagsId()));
这在代码中造成了很多重复,因为在我的服务实体的create和update方法之间,有很多相同的代码。
问题 2:
根据我的问题 1,如何轻松地将我的两个 DTO 映射到同一个实体而不重复代码 2x?
代码示例 - PostService (见评论)
这是一个更新示例,但create 的代码几乎相同,我该如何继续?
@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));
}
=================================
更新:
根据要求,找到下面的代码。
控制器:
@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();
}
}
创建后请求:
@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());
}
}
服务:
@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));
}
}
【问题讨论】:
-
您需要添加更多代码以便我们为您提供帮助。从
UpdatePostRequest、CreatePostRequest开始,公开两个端点的控制器以及update和create方法的代码。谢谢! -
@JoãoDias 我按要求添加了代码,但请注意服务方法尚未完成,因为我只是不知道如何在验证标签关系时正确注释我作为实体的请求确保它存在。感谢您的帮助。
标签: spring spring-boot hibernate modelmapper