{"id":1596,"date":"2021-01-25T14:33:57","date_gmt":"2021-01-25T05:33:57","guid":{"rendered":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=1596"},"modified":"2024-03-05T22:53:27","modified_gmt":"2024-03-05T13:53:27","slug":"mapstruct-%ec%82%ac%ec%9a%a9%ed%95%98%ea%b8%b0","status":"publish","type":"post","link":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=1596","title":{"rendered":"MapStruct \uc0ac\uc6a9\ud558\uae30"},"content":{"rendered":"<h1>MapStruct \uc0ac\uc6a9\ud558\uae30<\/h1>\n<p><code>MapStruct<\/code> \ub97c \uc774\uc6a9\ud558\uba74 DTO &#8211; Entity \uac04 \ub9e4\ud551\uc744 \uac04\ud3b8\ud558\uac8c \ud560 \uc218 \uc788\uace0, \ub354\ubd88\uc5b4 Entity \uc5c5\ub370\uc774\ud2b8 \ucf54\ub4dc\ub97c \ub9e4\uc6b0 \uac04\ub2e8\ud558\uac8c \uc904\uc77c \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<h2>\uc758\uc874\uc131 \ucd94\uac00<\/h2>\n<pre><code class=\"language-groovy\">dependencies {\n    \/\/ ......\n    implementation &#039;org.mapstruct:mapstruct:1.4.1.Final&#039;\n    compileOnly &#039;org.projectlombok:lombok&#039;\n    compileOnly &#039;org.projectlombok:lombok-mapstruct-binding:0.2.0&#039;\n    annotationProcessor &#039;org.projectlombok:lombok&#039;\n    annotationProcessor &#039;org.mapstruct:mapstruct-processor:1.4.1.Final&#039;\n    \/\/ ......\n}<\/code><\/pre>\n<h2>DTO \u2013 Entity \uc0dd\uc131<\/h2>\n<p>DTO \uc640 Entity \uc758 \ud544\ub4dc\uba85\uc744 1:1 \ub85c \uc77c\uce58\uc2dc\ucf1c\uc57c \ucf54\ub529\uc774 \ud3b8\ud574\uc9d1\ub2c8\ub2e4.<\/p>\n<p><font color=red><br \/>\n<code>@Setter<\/code>, <code>@Getter<\/code>, <code>@NoArgsConstructor<\/code> \uac00 \ucd94\uac00\ub418\uc5b4 \uc788\ub294\uc9c0 \ud56d\uc0c1 \ud655\uc778\ud55c\ub2e4.<br \/>\n\uc5d0\ub7ec\uc758 95% \uac00 \uc5d0\ub108\ud14c\uc774\uc158 \ub204\ub77d\uc785\ub2c8\ub2e4.<br \/>\n<\/font><\/p>\n<pre><code class=\"language-java\">@Setter\n@Getter\n@NoArgsConstructor\n@Entity\npublic class Brand extends BaseTimeEntity implements Persistable&lt;String&gt; {\n\n    @Id\n    private String brandId;\n\n    private String partnerId;\n    private String brandName;\n    private String useyn = &quot;Y&quot;;\n\n    public Brand(String brandId) {\n        this.brandId = brandId;\n    }\n\n    @Override\n    public String getId() {\n        return brandId;\n    }\n\n    @Override\n    public boolean isNew() {\n        return getRegdate() == null;\n    }\n}<\/code><\/pre>\n<pre><code class=\"language-java\">@Getter\n@Setter\n@NoArgsConstructor\npublic class BrandResponseDto {\n    private String brandId;\n    private String partnerId;\n    private String brandName;\n    private String useyn;\n    private LocalDateTime regdate;\n    private LocalDateTime lastupdate;\n}<\/code><\/pre>\n<p><code>RequestDto<\/code> \uc5d0\ub294 insert\/update \ud560 \ub370\uc774\ud0c0\ub9cc \ub0a8\uaca8\ub193\uc2b5\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-java\">@Getter\n@Setter\n@NoArgsConstructor\npublic class BrandCreateRequestDto {\n    private String partnerId;\n    private String brandName;\n}<\/code><\/pre>\n<pre><code class=\"language-java\">@Getter\n@Setter\n@NoArgsConstructor\npublic class BrandUpdateRequestDto {\n    private String brandName;\n    private String useyn;\n}<\/code><\/pre>\n<h2>GenericMapper \uc0dd\uc131<\/h2>\n<p>DTO &#8211; Entity \uac04 \ud544\ub4dc\uba85\uc744 \ub3d9\uc77c\ud558\uac8c \uc0dd\uc131\ud55c \uacbd\uc6b0 \uc218\ub3d9 \ub9e4\ud551\uc744 \uc544\uc608 \uc548\ud574\ub3c4 \ub429\ub2c8\ub2e4.<\/p>\n<p><code>updateFromDto()<\/code> \ub294 Entity \uc5c5\ub370\uc774\ud2b8\uc2dc \uac12\uc774 null \uc774 \uc544\ub2cc \uac12\ub9cc \uc5c5\ub370\uc774\ud2b8 \ud558\ub3c4\ub85d \ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-java\">public interface GenericMapper&lt;D, E&gt; {\n    D toDto(E e);\n    List&lt;D&gt; toDto(List&lt;E&gt; e);\n    void updateFromDto(D dto, @MappingTarget E entity);\n}<\/code><\/pre>\n<pre><code class=\"language-java\">@Mapper(\n    componentModel = &quot;spring&quot;,\n    unmappedTargetPolicy = ReportingPolicy.IGNORE,\n    nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE\n)\npublic interface BrandMapper extends GenericMapper&lt;BrandDto, Brand&gt; {\n}<\/code><\/pre>\n<h2>Service \uc0dd\uc131<\/h2>\n<p><code>update<\/code> \uac00 \ub9e4\uc6b0 \uac04\ub2e8\ud574\uc9d1\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-java\">@Service\npublic class BrandService {\n\n    private final BrandMapper mapper = Mappers.getMapper(BrandMapper.class);\n\n    \/\/ ......\n\n    @Transactional\n    public ResponseEntity&lt;?&gt; create(BrandCreateRequestDto dto) {\n        Brand entity = new Brand();\n        converter.updateFromDto(dto, entity);\n        return ResponseEntity.ok(new ApiResponseWithData(ResponseCode.OK, converter.toDto(repository.save(entity))));\n    }\n\n    @Transactional\n    public ResponseEntity&lt;?&gt; update(String brandId, BrandUpdateRequestDto dto) {\n        Optional&lt;Brand&gt; brand = repository.findById(brandId);\n        assert brand.isPresent();\n        converter.updateFromDto(dto, brand.get());\n        repository.save(brand.get());\n        return ResponseEntity.ok(new ApiResponseMessage(ResponseCode.OK));\n    }\n\n    public ResponseEntity&lt;?&gt; get(String brandId) {\n        Optional&lt;Brand&gt; brand = repository.findById(brandId);\n        assert brand.isPresent();\n        return ResponseEntity.ok(new ApiResponseWithData(ResponseCode.OK, converter.toDto(brand.get())));\n    }\n\n    public ResponseEntity&lt;?&gt; search(SearchBrandRequestDto dto) {\n        Page&lt;BrandResponseDto&gt; dtos = repository.search(dto).map(converter::toDto);\n        return ResponseEntity.ok(new ApiResponseWithData(ResponseCode.OK, dtos));\n    }\n}<\/code><\/pre>\n<h2>\ub72c\uae08\uc5c6\ub294 \uc624\ub958\ubc1c\uc0dd<\/h2>\n<p>\uc774\ub530\uae08 Mapper \uad00\ub828 \uc624\ub958\uac00 \ub72c\uae08\uc5c6\uc774 \ubc1c\uc0dd\ud569\ub2c8\ub2e4.<\/p>\n<p>\uc774\ub7f4\ub550 grable build clean \ud6c4 \ub2e4\uc2dc \uc2e4\ud589\ud558\uba74 \uc815\uc0c1\uc801\uc73c\ub85c \uc2e4\ud589\ub429\ub2c8\ub2e4.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>MapStruct \uc0ac\uc6a9\ud558\uae30 MapStruct \ub97c \uc774\uc6a9\ud558\uba74 DTO &#8211; Entity \uac04 \ub9e4\ud551\uc744 \uac04\ud3b8\ud558\uac8c \ud560 \uc218 \uc788\uace0, \ub354\ubd88\uc5b4 Entity \uc5c5\ub370\uc774\ud2b8 \ucf54\ub4dc\ub97c \ub9e4\uc6b0 \uac04\ub2e8\ud558\uac8c \uc904\uc77c \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc758\uc874\uc131 \ucd94\uac00 dependencies { \/\/ &#8230;&#8230; implementation &#039;org.mapstruct:mapstruct:1.4.1.Final&#039; compileOnly &#039;org.projectlombok:lombok&#039; compileOnly &#039;org.projectlombok:lombok-mapstruct-binding:0.2.0&#039; annotationProcessor &#039;org.projectlombok:lombok&#039; annotationProcessor &#039;org.mapstruct:mapstruct-processor:1.4.1.Final&#039; \/\/ &#8230;&#8230; } DTO \u2013 Entity \uc0dd\uc131 DTO \uc640 Entity \uc758 \ud544\ub4dc\uba85\uc744 1:1 \ub85c \uc77c\uce58\uc2dc\ucf1c\uc57c \ucf54\ub529\uc774\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=1596\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[],"class_list":["post-1596","post","type-post","status-publish","format-standard","hentry","category-java"],"_links":{"self":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/1596","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1596"}],"version-history":[{"count":26,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/1596\/revisions"}],"predecessor-version":[{"id":8685,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/1596\/revisions\/8685"}],"wp:attachment":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1596"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1596"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1596"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}