{"componentChunkName":"component---src-templates-post-template-jsx","path":"/works/posts/2021-04-20--001","result":{"data":{"site":{"siteMetadata":{"title":"Blog by Eunyoung","subtitle":"작업 기록 블로그","copyright":"© All rights reserved.","author":{"name":"EunYoung","twitter":"#"},"disqusShortname":"","url":"https://ssongey.github.io"}},"markdownRemark":{"id":"08f36c42-65f1-5ae0-94c1-5bf641deaf94","html":"<p>요즘 FMS 프로젝트에 대한 리펙터링을 열심히 진행하고 있다.<br>\n그 중 가장 초점을 맞추고 있는 작업은 Request/Response 객체로 사용되고 있는 Entity를 Dto로 바꾸는 것이다.<br>\n그래서 Dto to Entity, Entity to Dto 의 편리성을 위해 Mapstruct 를 도입하였고, 큰 문제가 없이 수월한 작업을 예상했는데<br>\n역시나.. 모든 리펙토링은 많은 고민이 필요하구나를 다시한번 느끼게 된다.  </p>\n<p>오늘 고민한 내용은 다음과 같다.<br>\n연관관계(FK)가 많은 Entity를 생성할때 <span class=\"text-mark__green\">모든 FK 객체는 어떻게 채울 것인가?</span><br>\nDTO가 가지고 있는 <span class=\"text-mark__green\">각 매핑 ID로 모두 조회</span>를 해야하나?  </p>\n<br>\n<p>일단, 간단하게 프로젝트를 구성하여 테스트를 했다.</p>\n<ul>\n<li>생성요청 DTO 클래스에는 customerId (FK) 값이 존재한다.</li>\n<li>\n<p>DTO 클래스 안에 DTO to Entity 메소드가 존재한다.</p>\n<ul>\n<li>Case1) customerId 로 repository에서 select 한 Customer 객체를 추입받는다</li>\n<li>Case2) customerId 필드만 넣어 Customer 객체 생성을 한다.</li>\n</ul>\n</li>\n</ul>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token annotation punctuation\">@NoArgsConstructor</span><span class=\"token punctuation\">(</span>access <span class=\"token operator\">=</span> <span class=\"token class-name\">AccessLevel</span><span class=\"token punctuation\">.</span>PRIVATE<span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">ReservationDto</span> <span class=\"token punctuation\">{</span>\n\n    <span class=\"token annotation punctuation\">@Getter</span>\n    <span class=\"token annotation punctuation\">@NoArgsConstructor</span>\n    <span class=\"token keyword\">public</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">CreateReq</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">private</span> <span class=\"token class-name\">Long</span> customerId<span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">private</span> <span class=\"token class-name\">PassengerType</span> passengerType<span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">private</span> <span class=\"token class-name\">String</span> usages<span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">private</span> <span class=\"token class-name\">String</span> luggage<span class=\"token punctuation\">;</span>\n\n        <span class=\"token comment\">//case1. customer id로 repository에서 select 한 값을 주입 받아 entity 에 주입</span>\n        <span class=\"token keyword\">public</span> <span class=\"token class-name\">ReservationPassenger</span> <span class=\"token function\">toEntity</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Customer</span> customer<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n            <span class=\"token class-name\">ReservationPassenger</span> reservationPassenger <span class=\"token operator\">=</span> <span class=\"token class-name\">ReservationDtoMapper</span><span class=\"token punctuation\">.</span>INSTANCE<span class=\"token punctuation\">.</span><span class=\"token function\">toReservationPassengerEntity</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n            reservationPassenger<span class=\"token punctuation\">.</span><span class=\"token function\">setCustomer</span><span class=\"token punctuation\">(</span>customer<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n            <span class=\"token keyword\">return</span> reservationPassenger<span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n\n        <span class=\"token comment\">//Case2. id로 customer id 객체 생성 후 entity 에 주입</span>\n        <span class=\"token keyword\">public</span> <span class=\"token class-name\">ReservationPassenger</span> <span class=\"token function\">toEntity</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n            <span class=\"token class-name\">Customer</span> customer <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Customer</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>customerId<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n            <span class=\"token class-name\">ReservationPassenger</span> reservationPassenger <span class=\"token operator\">=</span> <span class=\"token class-name\">ReservationDtoMapper</span><span class=\"token punctuation\">.</span>INSTANCE<span class=\"token punctuation\">.</span><span class=\"token function\">toReservationPassengerEntity</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n            reservationPassenger<span class=\"token punctuation\">.</span><span class=\"token function\">setCustomer</span><span class=\"token punctuation\">(</span>customer<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n            <span class=\"token keyword\">return</span> reservationPassenger<span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p><span class=\"title__sub1\">case1. customer id로 repository에서 select 한 값을 주입 받아 entity에 주입</span></p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">public</span> <span class=\"token class-name\">ReservationPassenger</span> <span class=\"token function\">toEntity</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Customer</span> customer<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token class-name\">ReservationPassenger</span> reservationPassenger <span class=\"token operator\">=</span> <span class=\"token class-name\">ReservationDtoMapper</span><span class=\"token punctuation\">.</span>INSTANCE<span class=\"token punctuation\">.</span><span class=\"token function\">toReservationPassengerEntity</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    reservationPassenger<span class=\"token punctuation\">.</span><span class=\"token function\">setCustomer</span><span class=\"token punctuation\">(</span>customer<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> reservationPassenger<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token comment\">// 호출 메소드 로직</span>\n<span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">createReservation</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">ReservationDto<span class=\"token punctuation\">.</span>CreateReq</span> req<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// customer id로 select</span>\n    <span class=\"token class-name\">Customer</span> customer <span class=\"token operator\">=</span> customerRepository<span class=\"token punctuation\">.</span><span class=\"token function\">findById</span><span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">.</span><span class=\"token function\">getCustomerId</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">orElseThrow</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">IllegalArgumentException</span><span class=\"token operator\">::</span><span class=\"token keyword\">new</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">ReservationPassenger</span> reservationPassenger <span class=\"token operator\">=</span> req<span class=\"token punctuation\">.</span><span class=\"token function\">toEntity</span><span class=\"token punctuation\">(</span>customer<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">ReservationPassenger</span> saved <span class=\"token operator\">=</span> reservationRepository<span class=\"token punctuation\">.</span><span class=\"token function\">save</span><span class=\"token punctuation\">(</span>reservationPassenger<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>그래.. 이게 정석이겠지,<br>\n그런데 Entity의 연관관계가 많으면? 저렇게 객체를 가져와서 매핑해야 하나?<br>\n실질적으로는 ID만 필요로 할 뿐인데?</p>\n<p><span class=\"title__sub1\">case2. customerId 필드만 넣어 Customer 객체 생성을 한 후 entity에 주입</span></p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">public</span> <span class=\"token class-name\">ReservationPassenger</span> <span class=\"token function\">toEntity</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Customer</span> customer<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token class-name\">Customer</span> customer <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Customer</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>customerId<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token class-name\">ReservationPassenger</span> reservationPassenger <span class=\"token operator\">=</span> <span class=\"token class-name\">ReservationDtoMapper</span><span class=\"token punctuation\">.</span>INSTANCE<span class=\"token punctuation\">.</span><span class=\"token function\">toReservationPassengerEntity</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    reservationPassenger<span class=\"token punctuation\">.</span><span class=\"token function\">setCustomer</span><span class=\"token punctuation\">(</span>customer<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> reservationPassenger<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token comment\">// 호출 메소드 로직</span>\n<span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">createReservation</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">ReservationDto<span class=\"token punctuation\">.</span>CreateReq</span> req<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token class-name\">ReservationPassenger</span> reservationPassenger <span class=\"token operator\">=</span> req<span class=\"token punctuation\">.</span><span class=\"token function\">toEntity</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">ReservationPassenger</span> saved <span class=\"token operator\">=</span> reservationRepository<span class=\"token punctuation\">.</span><span class=\"token function\">save</span><span class=\"token punctuation\">(</span>reservationPassenger<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>헉! DB에는 문제없이 잘 매핑이 된다!<br>\n그럼 존재하지 않는 ID를 넣으면 어떻게 되지?</p>\n<br>\n<p>오~ 역시<br>\ncould not execute statement; SQL [n/a]; constraint 오류가 발생한다.<br>\n똑똑하구로..  </p>\n<div class=\"gatsby-highlight\" data-language=\"cmd\"><pre class=\"language-cmd\"><code class=\"language-cmd\">org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: \nReferential integrity constraint violation: &quot;FKT1K88T0M3HKQGVYFI365S5KV8: \nPUBLIC.RESERVATION_PASSENGER FOREIGN KEY(CUSTOMER_ID) REFERENCES PUBLIC.CUSTOMER(ID) (2)&quot;; SQL statement:</code></pre></div>\n<br>\n<p>물론 매핑 ID의 검증을 위해 첫번째 방법이 당연하다는건 알지만,<br>\n매핑 ID의 검증이 필요 없는 경우는 두번째 방법을 써도 되지 않을까?  </p>\n<p>좀 더 나은 방법이 없는지 더 고민 해봐야 겠다.</p>","fields":{"tagSlugs":["/tags/spring-boot/","/tags/dto/"],"slug":"/works/posts/2021-04-20--001"},"frontmatter":{"title":"[작업로그] Dto to Entity에 대한 고민","tags":["SpringBoot","DTO"],"date":"2021-04-20","description":""}}},"pageContext":{"slug":"/works/posts/2021-04-20--001"}},"staticQueryHashes":[]}