(5) WEB 확장, 구현체
12.5.1 설정
- 스프링 데이터 프로젝트는 스프링 MVC에서 사용할 수 있는 편리한 기능을 제공한다.
WebAppConfig
자바 클래스 파일에@EnableSpringDataWebSupport
어노테이션을 사용해도메인 클래스 컨버터
와페이징
과정렬
을 위한 기능 적용
=> HandlerMethodArgumentResolver
가 스프링 빈으로 등록된다.
12.5.2 도메인 클래스 컨버터 기능
식별자로 도메인 클래스를 바로 바인딩해주는 기능.
org.springframework.data.repository.support.DomainClassConverter
등록
@Controllerpublic class MemberController {@RequestMapping("member/memberUpdateForm")public String memberUpdateForm(@RequestParam("id") Member member, Model model){model.addAttribute("member", member);return "member/memberSaveForm";}}
@RequestParam("id") Member member
부분에서 id를 넘겨받지만, 도메인 클래스 컨버터
가 중간에 동작해서 id를 회원 엔티티 객체로 변환해서 넘겨준다.
해당 엔티티와 관련된 리포지토리를 사용해서 엔티티를 찾는다.
여기서는 회원 리포지토리를 통해서 회원 id로 회원 엔티티를 찾는다.
이때, 도메인 클래스 컨버터를 통해 넘어온 회원 엔티티를 컨트롤러에서 직접 수정해도 실제 데이터베이스에 반영되지 않는다.
OSIV 사용 X
조회한 엔티티는 준영속 상태 => 변경 감지기능이 동작하지 않는다. 수정한 내용은
merge
를 사용해서 데이터베이스에 반영OSIV 사용 O
조회한 엔티티는 영속 상태 => 컨트롤러와 뷰에서는 영속성 컨텍스트를 플러시하지 않는다.
수정한 내용을 데이터베이스에 반영하려면 트랜잭션을 시작하는 서비스 계층을 호출해야 한다. 해당 서비스 계층 종료 시 플러시 + 트랜잭션 커밋 발생하여 변경 내용이 데이터베이스에 반영
12.5.3 페이징과 정렬 기능
HandlerMethodArgumentResolver
를 통해 스프링 MVC 에서 스프링 데이터가 제공하는 페이징
과 정렬
기능을 편리하게 사용
- 페이징 기능 :
PageableHandlerMethodArgumentResolver
- 정렬 기능 :
PageableHandlerMethodArgumentResolver
페이징과 정렬 예제
@RequestMapping(value = "/members", method = RequestMethod.GET)public String list(Pageable pageable, Model model){ // 파라미터로 Pageable을 받는다. Pageable은 요청 파라미터 정보로 만들어진다.Page<Member> page = memberService.findMembers(pageable);model.addAttribute("members", page.getContent());return "members/memberList";}
Pageable의 요청 파라미터
page : 현재 페이지, 0부터 시작
size : 한 페이지에 노출할 데이터 건수
sort : 정렬 조건 (asc, desc)
예시) /members?page=0&size=20&sort=name, desc&sort=address.city
접두사
사용해야 할 페이징 정보가 둘 이상이면 접두사를 사용해 구분 가능 @Qualifier
사용. 접두사명_
으로 구분
public String list(@Qualifier("member") Pageable memberPageable,@Qualifier("order") Pageable orderPageable, ...)
예시) /members?member_page=0&order_page=1
기본값
Pageable
의 기본값은 page=0, size=20 이다.
기본값 변경 하려면 @PageableDefault
어노테이션을 사용한다.
@RequestMapping(value = "/members_page", method = RequestMethod.GET)public String list(@PageableDefault(size=12, sort="name",direction=Sort.Direction.DESC) Pageable pageable) {...}
12.5.4 스프링 데이터 JPA가 사용하는 구현체
스프링 데이터 JPA가 제공하는 공통 인터페이스는 org.springframework.data.jpa.repository.support.SimpleJpqRepository
클래스가 구현
1. @Repository 적용
- JPA 예외를 스프링이 추상화한 예외로 변환한다.
2. @Transactional 적용
JPA의 모든 변경은 트랜잭션 안에서 이루어져야 한다.
스프링 데이터 JPA가 제공하는 공통 인터페이스를 사용하면 데이터 변경 메소드에 @Transactional
로 처리되어 있다.
- 서비스 계층에서 트랜잭션을 시작하지 않으면, 리포지토리에서 트랜잭션을 시작.
- 서비스 계층에서 트랜잭션을 시작했으면, 리포지토리도 해당 트랜잭션을 전파받아 그대로 사용
3. @Transactional(readOnly = true)
데이터를 조회하는 메소드에는 readOnly = true
옵션이 적용되어 있다.
=> 플러시를 생략해서 약간의 성능 향상
4. save() 메소드
저장할 엔티티가 새로운 엔티티면 저장(persist), 이미 있는 엔티티면 병합(merge)
새로운 엔티티 판단 기본 전략은 엔티티의 식별자로 판단
- 식별자가 객체일 때, null 이면 새로운 엔티티로 판단.
- 식별자가 자바 기본 타입일 때, 숫자 0 값이면 새로운 엔티티로 판단.