도메인 클래스 컨버터
아래와 같이 member의 id인 pk로 멤버를 @PathVariable을 사용하여 조회하는 컨트롤러가 있다고 해보자.
@RestController
@RequiredArgsConstructor
public class MemberController {
private final MemberRepository memberRepository;
@GetMapping("/members/{id}")
public String findMember(@PathVariable("id") Long id){
Member member = memberRepository.findById(id).orElseGet(()->new Member("emptyMember"));
return member.getUsername();
}
}
member의 id가 1이고, username이 "userA"일 때 아래와 같이 요청하면 위의 findMember 컨트롤러는 "userA"를 반환해줄 것이다. (물론 id가 1인 member가 있는 경우에)
localhost:8080/members/1 //서버로부터 "userA" 응답받음
하지만 이와 같은 경우에 도메인 클래스 컨버터를 사용하여 더 쉽게 조회하는 방법이 있다.
@RestController
@RequiredArgsConstructor
public class MemberController {
@GetMapping("/members2/{id}")
public String findMember2(@PathVariable("id") Member member){
return member.getUsername();
}
}
위와 같이 조회 시 pk를 사용할 경우, @PathVariable("id") Member member를 사용하면 컨트롤러의 코드 상으로 리퍼지토리를 거치치 않고, 바로 조회할 수 있도록 해준다.
하지만 도메인 클래스 컨버터는 아주 간단한 경우에만, 사용해야 한다면 조회시에만 사용하는 것을 권장한다.
페이징과 정렬
- 스프링 데이터가 제공하는 페이징과 정렬 기능을 스프링 MVC에서 편리하게 사용할 수 있다.
이전에 Page인터페이스를 페이징을 위해 사용하였는데, 컨트롤러에서 바로 Page<Member>타입을 반환하고 컨트롤러의 인자로 Pageable 인터페이스를 받으면 그에 맞게 JSON을 반환해준다.(현재 RestController 사용중)
@RestController
@RequiredArgsConstructor
public class MemberController {
private final MemberRepository memberRepository;
@GetMapping("/members")
public Page<Member> list(Pageable pageable){
Page<Member> page = memberRepository.findAll(pageable);
return page;
}
//PostConstruct로 회원 100명 생성
@PostConstruct
public void init(){
for(int i=0; i<100; i++)
memberRepository.save(new Member("user"+i, i, null));
}
}
이제 해당 url로 요청을 날려보면
localhost:8080/members
아래와 같이 JSON으로 데이터가 잘 넘어오는 것을 볼 수 있다.
그리고 심지어 아래와 같이 "?page=0" 쿼리 스트링을 붙여주면 첫페이지를 가져다준다.
localhost:8080/members?page=0
(default 값이 20이라 20개의 데이터만 가져다준다. id는 1부터 시작해서 1씩 증가 )
그리고 아래처럼 size까지 붙여주면 3개만을 limit으로 가져온다.
localhost:8080/members?page=0&size=3
또한 아래와 같이 sort조건을 추가할 수도 있다.
http://localhost:8080/members?page=0&size=3&sort=id //3개씩 첫 페이지, id 기준 오름차순 정렬
http://localhost:8080/members?page=0&size=3&sort=id,desc //3개씩 첫 페이지, id 기준 내림차순 정렬
글로벌로 디폴트 값 설정하기 :
만약 위처럼 쿼리 스트링을 넣지 않으면 스프링이 지정한 기본값으로 size, sort등이 정해진다. 이와 같은 기본값을 수정할 수 있다.
data:
web:
pageable:
default-page-size: 10 #page default size는 10으로
max-page-size: 2000 #최대 페이지 size
지역적으로 디폴트 값 설정하기 :
@PageableDefault를 사용하여 가능하다.
@GetMapping("/members")
public Page<Member> list(@PageableDefault(size = 5, sort="username") Pageable pageable){
Page<Member> page = memberRepository.findAll(pageable);
return page;
}
(물론 지역적 디폴트 값 설정이 글로벌 설정보다 우선한다.)
DTO로 반환하기
전에도 엔티티를 그대로 반환하는 것은 절대 안된다하였다. 하여 아래처럼 map을 사용하여 Dto로 변환하여 반환해준다.
@RestController
@RequiredArgsConstructor
public class MemberController {
private final MemberRepository memberRepository;
private final TeamRepository teamRepository;
@GetMapping("/members")
public Page<MemberDto> list(@PageableDefault(size = 5, sort="username") Pageable pageable){
Page<MemberDto> dtoPage = memberRepository.findAll(pageable)
.map((m) -> new MemberDto(m.getId(), m.getUsername(), m.getTeam().getName()));/*map으로 DTO로 전환*/
return dtoPage;
}
@PostConstruct
public void init(){
Team team = new Team("ManCity");
teamRepository.save(team);
for(int i=0; i<100; i++)
memberRepository.save(new Member("user"+i, i, team));
}
}
localhost:8080/members 요청 결과 :
참고:
엔티티는 DTO를 모르게, DTO는 엔티티를 알아도 된다. 즉 아래와 같은 코드는 편리하고, 사용해도 된다. 하지만 그 반대는 안된다.
import lombok.Data;
import study.datajpa.entity.Member;
@Data
public class MemberDto {
private Long id;
private String username;
private String teamName;
public MemberDto(Member member) {
this.id = member.getId();
this.username = member.getUsername();
this.teamName = member.getTeam().getName();
}
}
이렇게 하면 컨트롤러의 코드도 줄일 수 있다.
@GetMapping("/members")
public Page<MemberDto> list(@PageableDefault(size = 5, sort="username") Pageable pageable){
return memberRepository.findAll(pageable).map(MemberDto::new);/*map으로 DTO로 전환*/
}
'JPA > 스프링 DATA JPA' 카테고리의 다른 글
Data JPA 14 - 나머지 기능들 1. Specifications, Query By Example (0) | 2022.01.12 |
---|---|
Data JPA 13 - 스프링 데이터 JPA 분석 (0) | 2022.01.11 |
Data JPA 11 Auditing (0) | 2022.01.08 |
Data JPA 10 사용자 정의 리포지토리 구현 (0) | 2022.01.08 |
Data JPA 09 JPA Hint (0) | 2022.01.08 |