-
#Spring Data Jpa - 12 확장기능 - Web 확장Spring Data JPA 2021. 3. 25. 12:00
Web 확장 - 도메인 클래스 컨버터
HTTP 파라미터로 넘어온 엔티티의 아이디로 엔티티 객체를 찾아서 바인딩
도메인 클래스 컨버터 사용 전
@RestController @RequiredArgsConstructor public class MemberController { private final MemberRepository memberRepository; @GetMapping("/members/{id}") public String findMember(@PathVariable("id") Long id) { Member member = memberRepository.findById(id).get(); return member.getUsername(); } }
도메인 클래스 컨버터 사용 후
@RestController @RequiredArgsConstructor public class MemberController { private final MemberRepository memberRepository; @GetMapping("/members/{id}") public String findMember(@PathVariable("id") Member member) { return member.getUsername(); } }
· HTTP 요청은 회원 id 를 받지만 도메인 클래스 컨버터가 중간에 동작해서 회원 엔티티 객체를 반환
· 도메인 클래스 컨버터도 리파지토리를 사용해서 엔티티를 찾음
-아이디가 pk가 들어간거라서 domain convertor라는 기술을 쓸수 있다.
-spring boot가 중간의 Member member = memberRepository.findById(id).get();컨버팅하는 과정을 다끝내고 인젝션해준것이다.
//이기능을 권장하지않은 pk가 외부에 공개되어 조회하는 경우는 드물고 쿼리 조회가 복잡해지면 쓸수 없다.주의: 도메인 클래스 컨버터로 엔티티를 파라미터로 받으면, 이 엔티티는 단순 조회용으로만 사용해야 한다.
(트랜잭션이 없는 범위에서 엔티티를 조회했으므로, 엔티티를 변경해도 DB에 반영되지 않는다)
Web 확장 - 페이징과 정렬
스프링 데이터가 제공하는 페이징과 정렬 기능을 스프링 MVC에서 편리하게 사용할 수 있다.
페이징과 정렬 예제
@GetMapping("/members") public Page<Member> list(Pageable pageable) { Page<Member> page = memberRepository.findAll(pageable); return page; }
파라미터로 Pageable 을 받을 수 있다.
Pageable 은 인터페이스, 실제는 org.springframework.data.domain.PageRequest 객체 생성
요청 파라미터
postman으로 request 날린 result · 예) /members?page=0&size=3&sort=id,desc&sort=username,desc
· page: 현재 페이지, 0부터 시작한다.
· size: 한 페이지에 노출할 데이터 건수
· sort: 정렬 조건을 정의한다. 예) 정렬 속성,정렬 속성...(ASC | DESC), 정렬 방향을 변경하고 싶으면 sort
파라미터 추가 ( asc 생략 가능)
Paging 기본값 변경
· 글로벌 설정: 스프링 부트 (현재는 yml에서 설정)
spring.data.web.pageable.default-page-size=20 /# 기본 페이지 사이즈/ spring.data.web.pageable.max-page-size=2000 /# 최대 페이지 사이즈/
· 개별 설정
@PageableDefault 어노테이션을 사용
@RequestMapping(value = "/members_page", method = RequestMethod.GET) public String list(@PageableDefault(size = 12, sort = “username”, direction = Sort.Direction.DESC) Pageable pageable) { ... }
접두사
· 페이징 정보가 둘 이상이면 접두사로 구분(한페이지에 페이징하는게 두개 이상이면)
· @Qualifier 에 접두사명 추가 "{접두사명}_xxx”
· 예제: /members?member_page=0&order_page=1
public String list( @Qualifier("member") Pageable memberPageable, @Qualifier("order") Pageable orderPageable, ...
Page 내용을 DTO로 변환하기
· entity를 외부에 노출하는 것은 내부설계를 밖에 노출하는 것이다. 규약에 의한게 의미가 없어지고, API 스팩이 바뀐다.
· 엔티티를 API로 노출하면 다양한 문제가 발생한다. 그래서 엔티티를 꼭 DTO로 변환해서 반환해야 한다.
· Page는 map() 을 지원해서 내부 데이터를 다른 것으로 변경할 수 있다.
Member DTO
@Data public class MemberDto { private Long id; private String username; public MemberDto(Member m) { this.id = m.getId(); this.username = m.getUsername(); } }
Page.map() 사용
@GetMapping("/members") public Page<MemberDto> list(Pageable pageable) { Page<Member> page = memberRepository.findAll(pageable); Page<MemberDto> pageDto = page.map(MemberDto::new); return pageDto; }
Page.map() 코드 최적화
@GetMapping("/members") public Page<MemberDto> list(Pageable pageable) { return memberRepository.findAll(pageable).map(MemberDto::new); }
Page를 1부터 시작하기
· 스프링 데이터는 Page를 0부터 시작한다.
· 만약 1부터 시작하려면?
· 1. Pageable, Page를 파리미터와 응답 값으로 사용히자 않고, 직접 클래스를 만들어서 처리한다. 그리고 직접 PageRequest(Pageable 구현체)를 생성해서 리포지토리에 넘긴다. 물론 응답값도 Page 대신에 직접 만들어서 제공해야 한다.
이런식으로 생성 · 2. spring.data.web.pageable.one-indexed-parameters 를 true 로 설정한다. 그런데 이 방법은 web에서 page 파라미터를 -1 처리 할 뿐이다. 따라서 응답값인 Page 에 모두 0 페이지 인덱스를 사용하는 한계가 있다.
one-indexed-parameters Page 1요청 ( http://localhost:8080/members?page=1 )
{ "content": [ ... ], "pageable": { "offset": 0, "pageSize": 10, "pageNumber": 0 //0 인덱스 }, "number": 0, //0 인덱스 "empty": false }
페이지 객체 안에 pagable이랑 여러가지 객체가 들어있는데 여기안에 데이터가 안맞다 여기안에 데이터들은 페이지 인덱스가 0인걸 가정하고 동작한다. 이런부분이 안맞는데 이걸 감안하고 쓰면 써도된다.
'Spring Data JPA' 카테고리의 다른 글
#Spring Data Jpa - 14 Projections (0) 2021.03.26 #Spring Data Jpa - 13 스프링 데이터 JPA 구현체 분석 (0) 2021.03.25 #Spring Data JPA - 11 확장기능 - Auditing (0) 2021.03.25 #Spring Data JPA - 9 쿼리메소드 -JPA Hint & Lock (0) 2021.03.24 #Spring Data JPA - 8 쿼리메소드 -@EntityGraph (0) 2021.03.24