EntityToDTOConversionforaSpringRESTAPI
2. Model Mapper
Let"s start by introducing the main library that we"re going to use to perform this entity-DTO conversion – ModelMapper.
We will need this dependency in the pom.xml:
1
2
3
4
5
<
dependency
>
<
groupId
>org.modelmapper</
groupId
>
<
artifactId
>modelmapper</
artifactId
>
<
version
>2.3.5</
version
>
</
dependency
>
To check if there"s any newer version of this library, go here.
We"ll then define the ModelMapper bean in our Spring configuration:
1
2
3
4
@Bean
public
ModelMapper modelMapper() {
return
new
ModelMapper();
}
3. The DTO
Next, let"s introduce the DTO side of this two-sided problem – Post DTO:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public
class
PostDto {
private
static
final
SimpleDateFormat dateFormat
=
new
SimpleDateFormat(
"yyyy-MM-dd HH:mm"
);
private
Long id;
private
String title;
private
String url;
private
String date;
private
UserDto user;
public
Date getSubmissionDateConverted(String timezone)
throws
ParseException {
dateFormat.setTimeZone(TimeZone.getTimeZone(timezone));
return
dateFormat.parse(
this
.date);
}
public
void
setSubmissionDate(Date date, String timezone) {
dateFormat.setTimeZone(TimeZone.getTimeZone(timezone));
this
.date = dateFormat.format(date);
}
// standard getters and setters
}
Note that the two custom date related methods handle the date conversion back and forth between the client and the server:
- getSubmissionDateConverted() method converts date String into a Date in server"s timezone to use it in the persisting Post entity
- setSubmissionDate() method is to set DTO"s date to Post‘s Date in current user timezone.
4. The Service Layer
Let"s now look at a service level operation – which will obviously work with the Entity (not the DTO):
1
2
3
4
5
6
7
8
9
10
public
List<Post> getPostsList(
int
page,
int
size, String sortDir, String sort) {
PageRequest pageReq
= PageRequest.of(page, size, Sort.Direction.fromString(sortDir), sort);
Page<Post> posts = postRepository
.findByUser(userService.getCurrentUser(), pageReq);
return
posts.getContent();
}
We"re going to have a look at the layer above service next – the controller layer. This is where the conversion will actually happen as well.
5. The Controller Layer
Let"s now have a look at a standard controller implementation, exposing the simple REST API for the Post resource.
We"re going to show here a few simple CRUD operations: create, update, get one and get all. And given the operations are pretty straightforward, we are especially interested in the Entity-DTO conversion aspects:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@Controller
class
PostRestController {
@Autowired
private
IPostService postService;
@Autowired
private
IUserService userService;
@Autowired
private
ModelMapper modelMapper;
@GetMapping
@ResponseBody
public
List<PostDto> getPosts(...) {
//...
List<Post> posts = postService.getPostsList(page, size, sortDir, sort);
return
posts.stream()
.map(
this
::convertToDto)
.collect(Collectors.toList());
}
@PostMapping
@ResponseStatus
(HttpStatus.CREATED)
@ResponseBody
public
PostDto createPost(
@RequestBody
PostDto postDto) {
Post post = convertToEntity(postDto);
Post postCreated = postService.createPost(post));
return
convertToDto(postCreated);
}
@GetMapping
(value =
"/{id}"
)
@ResponseBody
public
PostDto getPost(
@PathVariable
(
"id"
) Long id) {
return
convertToDto(postService.getPostById(id));
}
@PutMapping
(value =
"/{id}"
)
@ResponseStatus
(HttpStatus.OK)
public
void
updatePost(
@RequestBody
PostDto postDto) {
Post post = convertToEntity(postDto);
postService.updatePost(post);
}
}
And here is our conversion from Post entity to PostDto:
1
2
3
4
5
6
private
PostDto convertToDto(Post post) {
PostDto postDto = modelMapper.map(post, PostDto.
class
);
postDto.setSubmissionDate(post.getSubmissionDate(),
userService.getCurrentUser().getPreference().getTimezone());
return
postDto;
}
And here is the conversion from DTO to an entity:
1
2
3
4
5
6
7
8
9
10
11
12
private
Post convertToEntity(PostDto postDto)
throws
ParseException {
Post post = modelMapper.map(postDto, Post.
class
);
post.setSubmissionDate(postDto.getSubmissionDateConverted(
userService.getCurrentUser().getPreference().getTimezone()));
if
(postDto.getId() !=
null
) {
Post oldPost = postService.getPostById(postDto.getId());
post.setRedditID(oldPost.getRedditID());
post.setSent(oldPost.isSent());
}
return
post;
}
So, as you can see, with the help of the model mapper, the conversion logic is quick and simple – we"re using the map API of the mapper and getting the data converted without writing a single line of conversion logic.
6. Unit Testing
Finally, let"s do a very simple test to make sure the conversions between the entity and the DTO work well:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public
class
PostDtoUnitTest {
private
ModelMapper modelMapper =
new
ModelMapper();
@Test
public
void
whenConvertPostEntityToPostDto_thenCorrect() {
Post post =
new
Post();
post.setId(1L);
post.setTitle(randomAlphabetic(
6
));
post.setUrl(
"www.test.com"
);
PostDto postDto = modelMapper.map(post, PostDto.
class
);
assertEquals(post.getId(), postDto.getId());
assertEquals(post.getTitle(), postDto.getTitle());
assertEquals(post.getUrl(), postDto.getUrl());
}
@Test
public
void
whenConvertPostDtoToPostEntity_thenCorrect() {
PostDto postDto =
new
PostDto();
postDto.setId(1L);
postDto.setTitle(randomAlphabetic(
6
));
postDto.setUrl(
"www.test.com"
);
Post post = modelMapper.map(postDto, Post.
class
);
assertEquals(postDto.getId(), post.getId());
assertEquals(postDto.getTitle(), post.getTitle());
assertEquals(postDto.getUrl(), post.getUrl());
}
}
7. Conclusion
This was an article on simplifying the conversion from Entity to DTO and from DTO to Entity in a Spring REST API, by using the model mapper library instead of writing these conversions by hand.
The full source code for the examples is available in the GitHub project.
以上是 EntityToDTOConversionforaSpringRESTAPI 的全部内容, 来源链接: utcz.com/z/513016.html