post-image

Spring Boot DTO Example – Convert từ Entity sang DTO

REST API Spring Data JPA

Trong bài hướng dẫn này, chúng ta sẽ học cách tạo 1 DTOs (Data Transfer Objects) class trong Spring Boot application và cách convert từ Entity sang DTO và ngược lại bằng thư viên ModelMapper.

Data Transfer Object Design Pattern là một design pattern được sử dụng thường xuyên. Về cơ bản thì nó được dùng để truyền data có nhiều attributes trong một lần truyền từ client đến server để tránh được nhiều request đến server.

Một lợi thế khác từ việc sử dụng DTO trên API RESTful được viết bằng Java (và trên Spring Boot), là có thể ẩn đi chi tiết các implementation của Object (JPA entity).

TÀI LIỆU HỌC LẬP TRÌNH

Việc để lộ các entity thông qua các điểm cuối có thể trở thành một vấn đề bảo mật. Nếu chúng ta không xử lý cẩn thận những thuộc tính thì có thể bị thay đổi bằng bất kỳ thao tác nào.

Hãy cùng bắt đầu với việc include thư viện ModelMapper, cái mà chúng ta sẽ sử dụng để convert từ Entity sang DTO và ngược lại.

ModelMapper Library

Mục tiêu của ModelMapper là làm cho việc mapping object đơn giản hơn. Bằng cách tự động define cách một object model map tới một object khác.

Đọc thêm về thư viện model mapper tại http://modelmapper.org/.

Thêm thư viện của ModelMapper vào pom.xml:

<dependency> <groupId>org.modelmapper</groupId> <artifactId>modelmapper</artifactId> <version>2.3.5</version> </dependency>
Code language: HTML, XML (xml)

Step 1: Thêm ModelMapper Library vào pom.xml

Thêm thư viện của ModelMapper vào pom.xml:

<dependency> <groupId>org.modelmapper</groupId> <artifactId>modelmapper</artifactId> <version>2.3.5</version> </dependency>
Code language: HTML, XML (xml)

Step 2: Define JPA Entity – Post.java

package com.hdd.model; import java.util.HashSet; import java.util.Set; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.UniqueConstraint; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor @Entity @Table(name = "posts", uniqueConstraints = {@UniqueConstraint(columnNames = {"title"})}) public class Post { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "title") private String title; @Column(name = "description") private String description; @Column(name = "content") private String content; }
Code language: JavaScript (javascript)

Step 3: Define DTO Class – PostDto.java

Hãy tạo class PostDto như sau:

package com.hdd.payload; import java.util.HashSet; import java.util.Set; import lombok.Data; @Data public class PostDto { private long id; private String title; private String description; private String content; }
Code language: CSS (css)

Step 4: Service

PostService interface:

package com.hdd.service; import java.util.List; import net.javaguides.springboot.model.Post; public interface PostService { List<Post> getAllPosts(); Post createPost(Post post); Post updatePost(long id, Post post); void deletePost(long id); Post getPostById(long id); }
Code language: PHP (php)

PostServiceImpl Class:

package com.hdd.service.impl; import java.util.List; import java.util.Optional; import org.springframework.stereotype.Service; import com.hdd.exception.ResourceNotFoundException; import com.hdd.model.Post; import com.hdd.repository.PostResository; import com.hdd.service.PostService; @Service public class PostServiceImpl implements PostService{ private final PostResository postRepository; public PostServiceImpl(PostResository postRepository) { super(); this.postRepository = postRepository; } @Override public List<Post> getAllPosts() { return postRepository.findAll(); } @Override public Post createPost(Post post) { return postRepository.save(post); } @Override public Post updatePost(long id, Post postRequest) { Post post = postRepository.findById(id) .orElseThrow(() -> new ResourceNotFoundException("Post", "id", id)); post.setTitle(postRequest.getTitle()); post.setDescription(postRequest.getDescription()); post.setContent(postRequest.getContent()); return postRepository.save(post); } @Override public void deletePost(long id) { Post post = postRepository.findById(id) .orElseThrow(() -> new ResourceNotFoundException("Post", "id", id)); postRepository.delete(post); } @Override public Post getPostById(long id) { Optional<Post> result = postRepository.findById(id); if(result.isPresent()) { return result.get(); }else { throw new ResourceNotFoundException("Post", "id", id); } // Post post = postRepository.findById(id) // .orElseThrow(() -> new ResourceNotFoundException("Post", "id", id)); //return post; } }
Code language: PHP (php)

Step 5: Configure ModelMapper Class a Spring Bean

Hãy cấu hình ModelMapper như là một Spring Bean để chúng ta có thể inject vào controller:

package com.hdd; import org.modelmapper.ModelMapper; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; @SpringBootApplication public class SpringbootBlogApiApplication { @Bean public ModelMapper modelMapper() { return new ModelMapper(); } public static void main(String[] args) { SpringApplication.run(SpringbootBlogApiApplication.class, args); } }
Code language: JavaScript (javascript)

Step 6: Controller Class

Trong Controller PostController, tôi đã inject ModelMapper và sử dụng các REST API khác nhau để convert từ Entity sang DTO và ngược lại:

THAM GIA KHÓA HỌC LẬP TRÌNH

package com.hdd.contoller; import java.util.List; import java.util.stream.Collectors; import org.modelmapper.ModelMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.hdd.model.Post; import com.hdd.payload.ApiResponse; import com.hdd.payload.PostDto; import com.hdd.service.PostService; @RestController @RequestMapping("/api/posts") public class PostController { @Autowired private ModelMapper modelMapper; private PostService postService; public PostController(PostService postService) { super(); this.postService = postService; } @GetMapping public List<PostDto> getAllPosts() { return postService.getAllPosts().stream().map(post -> modelMapper.map(post, PostDto.class)) .collect(Collectors.toList()); } @GetMapping("/{id}") public ResponseEntity<PostDto> getPostById(@PathVariable(name = "id") Long id) { Post post = postService.getPostById(id); // convert entity to DTO PostDto postResponse = modelMapper.map(post, PostDto.class); return ResponseEntity.ok().body(postResponse); } @PostMapping public ResponseEntity<PostDto> createPost(@RequestBody PostDto postDto) { // convert DTO to entity Post postRequest = modelMapper.map(postDto, Post.class); Post post = postService.createPost(postRequest); // convert entity to DTO PostDto postResponse = modelMapper.map(post, PostDto.class); return new ResponseEntity<PostDto>(postResponse, HttpStatus.CREATED); } // change the request for DTO // change the response for DTO @PutMapping("/{id}") public ResponseEntity<PostDto> updatePost(@PathVariable long id, @RequestBody PostDto postDto) { // convert DTO to Entity Post postRequest = modelMapper.map(postDto, Post.class); Post post = postService.updatePost(id, postRequest); // entity to DTO PostDto postResponse = modelMapper.map(post, PostDto.class); return ResponseEntity.ok().body(postResponse); } @DeleteMapping("/{id}") public ResponseEntity<ApiResponse> deletePost(@PathVariable(name = "id") Long id) { postService.deletePost(id); ApiResponse apiResponse = new ApiResponse(Boolean.TRUE, "Post deleted successfully", HttpStatus.OK); return new ResponseEntity<ApiResponse>(apiResponse, HttpStatus.OK); } }
Code language: JavaScript (javascript)

createPost():

Tổng hợp 200+ tài liệu, sách, bài thực hành, video hướng dẫn lập trình… từ cơ bản đến nâng cao

@PostMapping public ResponseEntity<PostDto> createPost(@RequestBody PostDto postDto) { // convert DTO to entity Post postRequest = modelMapper.map(postDto, Post.class); Post post = postService.createPost(postRequest); // convert entity to DTO PostDto postResponse = modelMapper.map(post, PostDto.class); return new ResponseEntity<PostDto>(postResponse, HttpStatus.CREATED); }
Code language: JavaScript (javascript)

updatePost():

// change the request for DTO // change the response for DTO @PutMapping("/{id}") public ResponseEntity<PostDto> updatePost(@PathVariable long id, @RequestBody PostDto postDto) { // convert DTO to Entity Post postRequest = modelMapper.map(postDto, Post.class); Post post = postService.updatePost(id, postRequest); // entity to DTO PostDto postResponse = modelMapper.map(post, PostDto.class); return ResponseEntity.ok().body(postResponse); }
Code language: JavaScript (javascript)

getPostById():

@GetMapping("/{id}") public ResponseEntity<PostDto> getPostById(@PathVariable(name = "id") Long id) { Post post = postService.getPostById(id); // convert entity to DTO PostDto postResponse = modelMapper.map(post, PostDto.class); return ResponseEntity.ok().body(postResponse); }
Code language: JavaScript (javascript)

Còn đây là method getAllPosts():

@GetMapping public List<PostDto> getAllPosts() { return postService.getAllPosts().stream().map(post -> modelMapper.map(post, PostDto.class)) .collect(Collectors.toList()); }
Code language: CSS (css)

Tổng kết

Hướng dẫn này đã chứng minh rằng cách convert từ Entity sang DTO và từ DTO sang Entity trong một Spring Boot application. Tôi đã sử dụng thư viện ModelMapper thay vì viết các conversion này bằng tay.

Chúc bạn thành công 😂

Các bài viết liên quan:

https://hocspringboot.net/2021/08/01/spring-data-jpa/

Leave a Reply

Your email address will not be published.