{도메인 클래스}.{메소드 이름} 형식의 Named 쿼리를 스프링 데이터 JPA 가 찾아서 실행한다
12.4.3 @Query, 리포지토리 메소드에 쿼리 정의
public interface MemberRepository extends JpaRepository<Member, Long> {
@Query("select m from Member where m.username = :name")
Member findByUsername(@Param("name") String username);
@Query(value = "SELECT * FROM MEMBER WHERE age = ?0", nativeQuery = true)
Member findByAge(Integer age);
}
@Query 어노테이션을 사용하여 실행할 메소드에 정적 쿼리를 직접 작성
가독성과 유지보수를 위해 이름 기반 파라미터 바인딩을 사용하자
12.4.5 벌크성 수정 쿼리
@Modifying(clearAutomatically = true)
@Query("update Product p set p.price = p.price * 1.1 where p.stockAmount < :stockAmount")
int bulkPriceUp(@Param("stockAmount") String stockAmount);
@Modifying 어노테이션 사용하여 벌크성 수정, 삭제 쿼리 생성
clearAutomatically = true 설정으로 벌크성 쿼리를 실행하고 나서 영속성 컨텍스트를 초기화 가능
PageRequest pageRequest = new PageRequest(0, 10, new Sort(Direction.DESC, "name"));
Page<Member> result = memberRepository.findByNameStartingWith("김", pageRequest);
List<Member> members = result.getContent(); // 조회된 데이터
int totalPages = result.getTotalPages(); // 전체 페이지 수
boolean hasNextPage = result.hasNextPage(); // 다음 페이지 존재 여부
Page 를 사용하면 스프링 데이터 JPA 는 검색된 전체 데이터 건수를 조회하는 count 쿼리를 추가로 호출함
Page 를 사용하는 클라이언트는 PageRequest 객체를 사용
12.5 명세(Specification)
JPA Criteria 가 사용된 개념인데, QueryDSL 사용으로 대체할 수 있어보여 생략함
12.6 사용자 정의 리포지토리 구현
public interface MemberRepositoryCustom {
public List<Member> findMemberCustom();
}
public interface MemberRepositoryCustomImpl implements MemberRepositoryCustom {
@Override
public List<Member> findMemberCustom() {
...
}
}
필요한 메소드를 직접 구현해야할 경우 사용
인터페이스 이름은 자유롭게 지으면 되지만, 구현체 클래스 이름은 {인터페이스 이름} + Impl 로 지어야함
(그래야 스프링 데이터 JPA 가 사용자 정의 구현 클래스로 인식함)
12.7 Web 확장
스프링 데이터 프로젝트가 제공하는 스프링 MVC 에서 편리하게 사용할 수 있는 기능
도메인 클래스 컨버터
페이징 & 정렬
12.7.1 설정
@Configuration
@EnableWebMvc
@EnableSpringDataWebSupport
public class WebAppConfig {
...
}
Web 확장 기능을 활성화하기 위해선 @EnableSpringDataWebSupport 를 사용하여 SpringDataWebConfiguration 을 스프링 빈으로 등록하면 된다
설정시 도메인 클래스 컨버터와 페이징&정렬 을 위한 HandlerMethodArgumentResolver 가 스프링 빈으로 등록된다
12.7.2 도메인 클래스 컨버터 기능
HTTP 파라미터로 넘어온 엔티티의 아이디로 엔티티 객체를 찾아서 바인딩해주는 역할
@Controller
public class MemberController {
@RequsetMapping("member/memberUpdateForm")
public String memberUpdateForm(@RequestParam("id") Member member, Model model) {
...
}
}
@RequestParam("id") Member member : HTTP 요청으로 id 를 받지만 도메인 클래스 컨버터가 Member 객체로 변환하여 전달
도메인 클래스 컨버터는 해당 엔티티 관련 리포지토리를 사용해서 조회한 결과를 전달한다
도메인 클래스 컨버터를 통해 넘어온 엔티티를 컨트롤러에서 직접 수정해도 DB 에는 반영되지 않는다
12.1 스프링 데이터 JPA 소개
12.1.1 스프링 데이터 프로젝트
12.2 스프링 데이터 JPA 설정
필요 라이브러리
환경설정
@EnableJpaRepositories
의 basePackages 값으로 리포지토리를 검색할 패키지 위치를 명시@EnableAutoConfiguration
에 의해 자동으로 설정된다12.3 공통 인터페이스 기능
JpaRepository
인터페이스는 JPA 에 특화된 기능을 추가로 제공12.4 쿼리 메소드 기능
12.4.1 메소드 이름으로 쿼리 생성
12.4.2 JPA NamedQuery
{도메인 클래스}.{메소드 이름}
형식의 Named 쿼리를 스프링 데이터 JPA 가 찾아서 실행한다12.4.3 @Query, 리포지토리 메소드에 쿼리 정의
@Query
어노테이션을 사용하여 실행할 메소드에 정적 쿼리를 직접 작성12.4.5 벌크성 수정 쿼리
@Modifying
어노테이션 사용하여 벌크성 수정, 삭제 쿼리 생성clearAutomatically = true
설정으로 벌크성 쿼리를 실행하고 나서 영속성 컨텍스트를 초기화 가능12.4.7 페이징과 정렬
Page
를 사용하면 스프링 데이터 JPA 는 검색된 전체 데이터 건수를 조회하는 count 쿼리를 추가로 호출함PageRequest
객체를 사용12.5 명세(Specification)
12.6 사용자 정의 리포지토리 구현
{인터페이스 이름} + Impl
로 지어야함12.7 Web 확장
12.7.1 설정
@EnableSpringDataWebSupport
를 사용하여SpringDataWebConfiguration
을 스프링 빈으로 등록하면 된다HandlerMethodArgumentResolver
가 스프링 빈으로 등록된다12.7.2 도메인 클래스 컨버터 기능
@RequestParam("id") Member member
: HTTP 요청으로 id 를 받지만 도메인 클래스 컨버터가 Member 객체로 변환하여 전달12.7.3 페이징과 정렬 기능
HandlerMethodArgumentResolver
사용PageableHandlerMethodArgumentResolver
SortHandlerMethodArgumentResolver
@PageableDefault(size = 12, sort = "name")
를 Pageable 앞에 사용하여 기본값을 변경할 수 있다@PageableDefault
만 사용한다면 page=0, size=10@Qualifier
어노테이션으로 접두사를 사용해 구분12.8 스프링 데이터 JPA 가 사용하는 구현체
SimpleJpaRepository
가 구현한다.@Repository
: JPA 예외를 스프링이 추상화한 예외로 변환@Transactional
: JPA 의 모든 변경(등록, 수정, 삭제)은 트랜잭션 안에서 이루어져야 하는데, 변경을 수행하는 메소드에 트랜잭션 처리를 위해 사용. 전파되므로 서비스 계층에서 사용시 리포지토리까지 적용됨.@Transactional(readOnly = true)
: 조회는 데이터 변경이 발생x. readOnly = true 옵션으로 플러시를 생략해서 약간의 성능 향상12.10 스프링 데이터 JPA 와 QueryDSL 통합
QueryDslPredicateExecutor
QueryDslRepositorySupport
QueryDslRepositorySupport
가 실무 레벨에 적합12.10.1 QueryDslPredicateExecutor
QueryDslPredicateExecutor
는 기능에 한계가 있음(join, fetch 등 사용 불가)12.10.2 QueryDslRepositorySupport