Penukaran Entiti Ke DTO untuk Spring REST API

REST Teratas

Saya baru sahaja mengumumkan kursus Learn Spring yang baru , yang berfokus pada asas-asas Spring 5 dan Spring Boot 2:

>> SEMAK KURSUS

1. Gambaran keseluruhan

Dalam tutorial ini, kami akan menangani penukaran yang perlu berlaku antara entiti dalaman aplikasi Spring dan DTO luaran (Objek Pemindahan Data) yang diterbitkan kembali kepada pelanggan.

2. Model Mapper

Mari kita mulakan dengan memperkenalkan perpustakaan utama yang akan kita gunakan untuk melakukan penukaran entiti-DTO ini - ModelMapper .

Kami memerlukan kebergantungan ini di pom.xml :

 org.modelmapper modelmapper 2.3.5 

Untuk memeriksa sama ada terdapat versi perpustakaan yang lebih baru, pergi ke sini.

Kami kemudian akan menentukan kacang ModelMapper dalam konfigurasi Spring kami:

@Bean public ModelMapper modelMapper() { return new ModelMapper(); }

3. DTO

Seterusnya, mari kita memperkenalkan sisi DTO dari masalah dua sisi ini - Post DTO:

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 } 

Perhatikan bahawa dua kaedah berkaitan tarikh khusus menangani penukaran tarikh berulang-ulang antara pelanggan dan pelayan:

  • Kaedah getSubmissionDateConverted () menukar tarikh String menjadi Date di zon waktu pelayan untuk menggunakannya dalam entiti Post yang masih ada
  • setSubmissionDate () kaedah untuk menetapkan tarikh DTO untuk Post 's Tarikh dalam zon waktu pengguna semasa.

4. Lapisan Perkhidmatan

Sekarang mari kita lihat operasi tahap perkhidmatan - yang jelas akan berfungsi dengan Entiti (bukan DTO):

public List getPostsList( int page, int size, String sortDir, String sort) { PageRequest pageReq = PageRequest.of(page, size, Sort.Direction.fromString(sortDir), sort); Page posts = postRepository .findByUser(userService.getCurrentUser(), pageReq); return posts.getContent(); }

Kita akan melihat lapisan di atas perkhidmatan seterusnya - lapisan pengawal. Di sinilah penukaran sebenarnya akan berlaku juga.

5. Lapisan Pengawal

Sekarang mari kita lihat pelaksanaan pengawal standard, memperlihatkan REST API ringkas untuk sumber Post .

Kami akan menunjukkan di sini beberapa operasi CRUD yang mudah: buat, kemas kini, dapatkan satu dan dapatkan semuanya. Dan memandangkan operasinya cukup mudah, kami sangat berminat dengan aspek penukaran Entity-DTO :

@Controller class PostRestController { @Autowired private IPostService postService; @Autowired private IUserService userService; @Autowired private ModelMapper modelMapper; @GetMapping @ResponseBody public List getPosts(...) { //... List 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); } }

Dan inilah penukaran kami dari entiti Pos ke PostDto :

private PostDto convertToDto(Post post) { PostDto postDto = modelMapper.map(post, PostDto.class); postDto.setSubmissionDate(post.getSubmissionDate(), userService.getCurrentUser().getPreference().getTimezone()); return postDto; }

Dan inilah penukaran dari DTO kepada entiti :

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; }

Oleh itu, seperti yang anda lihat, dengan bantuan model mapper, logik penukaran cepat dan mudah - kami menggunakan API peta mapper dan membuat data ditukar tanpa menulis satu baris logik penukaran.

6. Ujian Unit

Akhirnya, mari lakukan ujian yang sangat mudah untuk memastikan penukaran antara entiti dan DTO berjalan dengan baik:

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. Kesimpulannya

Ini adalah artikel untuk mempermudah penukaran dari Entity ke DTO dan dari DTO ke Entity dalam Spring REST API , dengan menggunakan model mapper library dan bukannya menulis penukaran ini dengan tangan.

Kod sumber penuh untuk contoh boleh didapati dalam projek GitHub.

REST bawah

Saya baru sahaja mengumumkan kursus Learn Spring yang baru , yang berfokus pada asas-asas Spring 5 dan Spring Boot 2:

>> SEMAK KURSUS