일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- mapstruct
- 데이터 압축
- Java Graphql
- java
- Java Rest
- tomcat jndi
- AfterMapping
- Srping MVC
- graphql
- 상호 인증
- Checked Exception
- Open Close Principal
- Request Body 여러 번 사용
- Reading HttpServletRequest Multiple Times
- Jndi DataSource
- Tomcat DBCP
- Sub Bytes
- requestheaderdto
- 개방 폐쇄 원칙
- NoUniqueBeanDefinitionException
- mTLS
- WildFly
- try - with - resources
- 이중정렬
- Socket is closed
- Unchecked Exception
- 바이트 절삭
- Graphql Client
- Java Singleton
- HandlerMethodArgumentResolver
- Today
- Total
Developer Sang Guy
Lombok @Builder 사용 시 MapStruct @AfterMapping 동작 이슈 본문
MappingTarget
@Getter
@ToString(exclude = "orders")
@Table(name = "members")
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@DynamicUpdate
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Integer age;
@Enumerated(EnumType.STRING)
private Gender gender;
@Setter
private String email;
@Column(name = "phone_number")
private String phoneNumber;
@Column(name = "join_at")
private LocalDateTime joinAt;
@OneToMany(mappedBy = "member", fetch = FetchType.LAZY)
private List<Order> orders = new ArrayList<>();
@PrePersist
private void onJoinAt() {
this.joinAt = LocalDateTime.now();
}
@Builder
public Member(Long id, String name, Integer age, Gender gender, String email, String phoneNumber) {
this.id = id;
this.name = name;
this.age = age;
this.gender = gender;
this.email = email;
this.phoneNumber = phoneNumber;
}
Source
import lombok.Data;
@Data
public class MemberRequest {
private String name;
private Integer age;
private String gender;
private String email;
private String phoneNumber;
}
Mapper
import org.mapstruct.AfterMapping;
import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget;
import org.mapstruct.ReportingPolicy;
import org.mapstruct.factory.Mappers;
import com.ahn.jpa.dto.MemberRequest;
import com.ahn.jpa.model.Member;
@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface MemberMapper {
MemberMapper MAPPER = Mappers.getMapper(MemberMapper.class);
Member mapToModel(MemberRequest request);
@AfterMapping
default void add(MemberRequest request, @MappingTarget Member member) {
member.setEmail("야호");
}
}
Mapper 구현체
import com.ahn.jpa.dto.MemberRequest;
import com.ahn.jpa.model.Member;
import com.ahn.jpa.model.enums.Gender;
import javax.annotation.Generated;
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2024-03-15T15:51:10+0900",
comments = "version: 1.5.3.Final, compiler: Eclipse JDT (IDE) 1.4.50.v20210914-1429, environment: Java 17.0.1 (Eclipse Adoptium)"
)
public class MemberMapperImpl implements MemberMapper {
@Override
public Member mapToModel(MemberRequest request) {
if ( request == null ) {
return null;
}
Member.MemberBuilder member = Member.builder();
member.age( request.getAge() );
member.email( request.getEmail() );
if ( request.getGender() != null ) {
member.gender( Enum.valueOf( Gender.class, request.getGender() ) );
}
member.name( request.getName() );
member.phoneNumber( request.getPhoneNumber() );
return member.build();
}
}
위와 같이 @AfterMapping을 설정하였지만 실제 구현된 코드에는 "add()" 메소드가 추가되어 있지 않다.
Builder를 사용할 경우엔 @TargetMapping에 실제 맵핑할 대상이 아닌 대상의 Builder를 추가해줘야 한다.
공식 문서에도 기재되어 있는 내용으로 보인다.
https://mapstruct.org/documentation/stable/reference/html/#customizing-mappings-with-before-and-after
MapStruct 1.5.5.Final Reference Guide
If set to true, MapStruct in which MapStruct logs its major decisions. Note, at the moment of writing in Maven, also showWarnings needs to be added due to a problem in the maven-compiler-plugin configuration.
mapstruct.org
Important: when using a builder, the @AfterMapping annotated method must have the builder as @MappingTarget annotated parameter so that the method is able to modify the object going to be build. The build method is called when the @AfterMapping annotated method scope finishes. MapStruct will not call the @AfterMapping annotated method if the real target is used as @MappingTarget annotated parameter.
문서 내용 적용하여 변경된 코드
import org.mapstruct.AfterMapping;
import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget;
import org.mapstruct.ReportingPolicy;
import org.mapstruct.factory.Mappers;
import com.ahn.jpa.dto.MemberRequest;
import com.ahn.jpa.model.Member;
@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface MemberMapper {
MemberMapper MAPPER = Mappers.getMapper(MemberMapper.class);
Member mapToModel(MemberRequest request);
@AfterMapping
default void add(MemberRequest request, @MappingTarget Member.MemberBuilder member) {
member.email("야호");
}
}
변경된 구현체
import com.ahn.jpa.dto.MemberRequest;
import com.ahn.jpa.model.Member;
import com.ahn.jpa.model.enums.Gender;
import javax.annotation.Generated;
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2024-03-15T16:03:36+0900",
comments = "version: 1.5.3.Final, compiler: Eclipse JDT (IDE) 1.4.50.v20210914-1429, environment: Java 17.0.1 (Eclipse Adoptium)"
)
public class MemberMapperImpl implements MemberMapper {
@Override
public Member mapToModel(MemberRequest request) {
if ( request == null ) {
return null;
}
Member.MemberBuilder member = Member.builder();
member.age( request.getAge() );
member.email( request.getEmail() );
if ( request.getGender() != null ) {
member.gender( Enum.valueOf( Gender.class, request.getGender() ) );
}
member.name( request.getName() );
member.phoneNumber( request.getPhoneNumber() );
add( request, member );
return member.build();
}
}
'Java' 카테고리의 다른 글
무작위 문자열, 바이트 배열 생성 (0) | 2024.07.22 |
---|---|
Stram Api를 활용한 정렬 (0) | 2024.07.18 |
Sub Bytes To String (0) | 2024.02.14 |
[JWT] Auth0을 활용한 JWT 생성 및 확인 (0) | 2023.04.10 |
[Java] Class에서 파일 읽어오기 (tomcat, wildfly) (0) | 2023.02.02 |