회원 등록
- Controller에서 Entity를 request로 바로 받는 것은 좋지 않음
- 따라서 requestDto를 사용해주어야함.
Member Entity
package jpabook.jpashop.domain;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Getter @Setter
public class Member {
@Id @GeneratedValue
@Column(name = "member_id")
private Long id;
private String name;
@Embedded
private Address address;
@JsonIgnore //JSON 직렬화 및 역직렬화 시에 특정 필드를 무시하도록 지시
@OneToMany(mappedBy = "member")
private List<Order> orders = new ArrayList<>();
}
Controller
package jpabook.jpashop.api;
import jpabook.jpashop.domain.Member;
import jpabook.jpashop.service.MemberService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
@RestController
@RequiredArgsConstructor
public class MemberApiController {
private final MemberService memberService;
@PostMapping("/api/v1/members")
public CreateMemberResponse saveMemberV1(@RequestBody @Valid Member member){
// 실제 개발할 때는 Entity를 그대로 받으면 안 됨.
Long id = memberService.join(member); // 회원 가입
return new CreateMemberResponse(id);
}
@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{
@NotEmpty
private String name;
}
@Data
static class CreateMemberResponse{
private Long id;
public CreateMemberResponse(Long id) {
this.id = id;
}
}
}
saveMemberV1과 같이 Entity를 그대로 받으면 생기는 문제점
- Member Entity의 칼럼명이 바뀌면 api 스펙도 바뀜.
- ex) name -> username으로 바뀌면 api의 스펙이 바뀜.
- Entity까지 확인해야 api 사용 방법을 알 수 있음.
대안으로 saveMemberV2와 같이 사용해줌
- CreateMemberRequest를 만들어주었음.
- Dto만 확인해도 어떤 값이 넘어오는지
- 필수 항목은 확인
- Entity가 변경돼도 api 스펙이 변함이 없음.
회원 수정
- Member 테이블의 id가 10인 hello를 new-hello로 바꿔보겠다.
- PutMappgin을 사용
- 회원 등록할 때와 같이 Dto 생성
@PutMapping("/api/v2/members/{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;
}
- Postman으로 작동되는지 확인

회원 조회
하면 안되는 방법 (V1)
- member 객체의 모든 정보가 반환이 됨.
- 만약 member에 있는 Address 정보가 반환할 필요가 없는 경우에는?
Entity에 @JsonIgnore 어노테이션을 사용하면 됨. 하지만 Address 정보가 필요할 때는? 다시 없애야되나? - 웹 애플리케이션을 만들 때 양방향 의존관계로 인해서 유지보수가 힘들어짐.
- 만약 member에 있는 Address 정보가 반환할 필요가 없는 경우에는?
@GetMapping("/api/v1/members")
public List<Member> membersV1(){
return memberService.findMembers();
}
따라서 Dto로 반환을 해주어야함 (V2)
@GetMapping("/api/v2/members")
public Result membersV2(){
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;
}

'JPA' 카테고리의 다른 글
[JPA API] 컬렉션 조회 최적화 (0) | 2024.01.25 |
---|---|
[JPA API] 주문, 배송정보, 회원 조회 API (0) | 2024.01.24 |
[JPQL] Named 쿼리 / 벌크 연산 (0) | 2024.01.22 |
[JPQL] 경로 표현식, 페치 조인 (1) | 2024.01.22 |
[JPQL] 조건식, 기본 함수 (0) | 2024.01.20 |