Mapstruct 란 클래스간 변환을 쉽게 하기 위해 등장한 라이브러리다
- DTO, Entity
: DTO 란 Data Transfer Object 를 말하며, 계층간 데이터 전송을 위해 만든 Bean 을 의미한다
Entity 란 DB 의 테이블과 매핑시키기 위한 자바 객체를 의미한다
Entity 에 정의해둔 필드변수 외에도 별도로 어떤 값을 유저로 부터 받아와야 한다거나 혹은 Entity 에는 없는 필드를 리턴시켜줘야 할때, DTO 를 이용하는데, 이런 작업을 가능하게하려면, Entity 와 DTO 간에 매핑과정이 필요하다
- maven 을 이용하는 경우
: maven 을 이용하는 경우 의존성 주입을 다음과 같이 해줘야 한다
pom.xml
<dependencies>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<!-- mapstruct -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>0.2.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>0.2.0</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
|
cs |
위와 같이 lombok 과 같이 쓰는 경우 mapstruct 라이브러리와 같이 연동하려면, <build> 부분에 lombok-mapstruct-binding 을 넣어줘야 한다.
- 예제
: 예를들어, 어떤 커뮤니티 사이트를 만든다고 가정하고, 작성할 글의 카테고리 관련한 API 를 만든다고 했을때, Entity 와 DTO 를 다음과 같이 구성했다고 하자
- Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
public class Category {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank(message = "Category name is required !")
private String name;
@NotBlank(message = "Description is required !")
private String description;
@OneToMany(fetch = FetchType.LAZY)
private List<Post> posts;
private Instant createdDate;
@ManyToOne(fetch = FetchType.LAZY)
private User user;
}
|
cs |
- DTO
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class CategoryDto {
private Long id;
private String name;
private String description;
private Integer postCount;
}
|
cs |
Entity 클래스엔, 필드 변수가 id, name, description, posts, createdDate, user 가 있지만,
DTO 클래스에는, id, name, description, postCount 로 구성되어 있다
두 클래스의 필드 변수가 서로 일치하지 않으므로, mapper 인터페이스를 선언해야 한다
- mapper interface
@Mapper(componentModel = "spring")
public interface CategoryMapper {
@Mapping(target = "postCount", expression = "java(mapPosts(category.getPosts()))")
CategoryDto mapCategoryToDto(Category category);
default Integer mapPosts(List<Post> postCount) {
return postCount.size();
}
@InheritInverseConfiguration
@Mapping(target = "posts", ignore = true)
@Mapping(target = "createdDate", expression = "java(java.time.Instant.now())")
Category mapDtoToCategory(CategoryDto categoryDto);
}
|
cs |
첫번째 메소드인 mapCategoryToDto 는 엔티티 클래스를 입력 받아서 DTO 로 변환시키는 작업을 하고
두번째 메소드는 그 반대로 DTO 를 엔티티로 변환시키는 역할을 맡고 있다
각 필드를 매핑시킬때는, @Mapping 어노테이션을 쓰고, target 은 매핑될 타겟 클래스의 타겟 필드 변수이름을 말하고
expression 은 어떤 값으로 넣을지에 대한 자바 구문을 넣는 속성값을 의미한다
그리고 여기엔 나와있지 않지만, source 라는 것도 있으며, target 과 매핑될 소스 객체의 소스 필드 변수이름을 의미한다
- References)
1. DTO, VO, DAO : genesis8.tistory.com/214
2. mapstruct : mapstruct.org/
'Spring' 카테고리의 다른 글
Spring Cloud 와 Microservice 란 (0) | 2021.07.01 |
---|---|
Swagger 를 통한 REST API 문서화 (0) | 2021.04.30 |
Lombok 이란? (0) | 2021.03.29 |
Spring Boot - Spring Data REST (0) | 2021.03.25 |
Spring Boot - DAO (0) | 2021.03.24 |