@RestController
@RequiredArgsConstructor
public class MemberApiController {
private final MemberService memberService;
@PostMapping("/api/v1/members")
public CreateMemberResponse saveMemberV1(@RequestBody @Valid Member member) {
Long id = memberService.join(member);
return new CreateMemberResponse(id);
}
@Data
static class CreateMemberResponse {
private Long id;
public CreateMemberResponse(Long id) {
this.id = id;
}
}
}
@Entity
@Getter @Setter
public class Member {
@Id @GeneratedValue
@Column(name = "member_id")
private Long id;
private String name;
@Embedded
private Address address;
@JsonIgnore
@OneToMany(mappedBy = "member")
private List<Order> orders = new ArrayList<>();
}
@RestController
는 @Controller
와 @ResponseBody
를 합친 것으로ㅡ 스프링이 제공해준다.
@RequestBody
는 JSON으로 온 데이터를 엔티티로 바꿔준다.
@PostMapping("/api/v2/members")
public CreateMemberResponse saveMemberV2(@RequestBody @Valid CreateMemberRequest request) {
Member member = new Member();
member.setName(request.getName());
Long id = memberService.join(member);
return new CreateMemberResponse(id);
}
@Data
static class CreateMemberRequest {
private String name;
}
@Data
static class CreateMemberResponse {
private Long id;
public CreateMemberResponse(Long id) {
this.id = id;
}
}
v2 - 요청값으로 Member 엔티티 대신에 별도의 DTO를 받는다.
@PutMapping("/api/v2/members/update/{id}")
public UpdateMemberResponse updateMemberV2(
@PathVariable("id") Long id,
@RequestBody @Valid UpdateMemberRequest request
) {
memberService.update(id, request.getName());
Member findMember = memberService.findOne(id);
return new UpdateMemberResponse(findMember.getId(), findMember.getName());
}
@Data
static class UpdateMemberRequest {
private String name;
}
@Data
@AllArgsConstructor
static class UpdateMemberResponse {
private Long id;
private String name;
}
조회 V1: 응답값으로 엔티티를 직접 외부에 노출
@GetMapping("/api/v1/members")
public List<Member> getMemberV1() {
return memberService.findMembers();
}
문제점
결론
회원조회 V2: 응답 값으로 엔티티가 아닌 별도의 DTO 사용
@GetMapping("/api/v2/members")
public Result memberV2() {
List<Member> findMembers = memberService.findMembers();
List<MemberDto> collect = findMembers.stream()
.map(m -> new MemberDto(m.getName()))
.collect(Collectors.toList());
return new Result(collect);
}
@Data
@AllArgsConstructor
static class Result<T> {
private T data;
}
@Data
@AllArgsConstructor
static class MemberDto {
private String name;
}
Result
클래스로 컬렉션을 감싸서 향후 필요한 필드를 추가할 수 있다.