본문 바로가기
Book

자바 ORM 표준 JPA 프로그래밍 - JPA 정리하기 (12) 스프링 데이터 JPA

by devLog by Ronnie's 2022. 11. 6.

자바 ORM 표준 JPA 프로그래밍 - JPA 정리하기 (12) 스프링 데이터 JPA

자바 ORM 표준 JPA 프로그래밍 - JPA 정리하기 (12) 스프링 데이터 JPA


 

12.1 스프링 데이터 JPA 소개

  • 스프링 데이터 JPA는 스프링 프레임워크에서 JPA를 편리하게 사용할 수 있도록 지원하는 프로젝트
  • 데이터 접근 계층을 개발할 때 구현 클래스 없이 인터페이스만 작성해도 기본적인 CRUD 개발 완료할 수 있음
  • 리포지토리 인터페이스의 구현체는 애플리케이션 실행 시점에 스프링 데이터 JPA가 생성해서 주입해준다.

12.1.1 스프링 데이터 프로젝트

  • 스프링 데이터 프로젝트는 JPA, 몽고 디비, 레디스, 하둡 등과 같은 다양한 데이터 저장소에 대한 접근을 추상화해서 개발자 편의를 제공하고 지루하게 반복하는 데이터 접근 코드를 줄여준다.
  • 스프링 데이터 JPA 프로젝트는 JPA에 특화된 기능을 제공한다.

12.3 공통 인터페이스 기능

  • 간단한 CRUD 기능을 공통으로 처리하는 JpaRepository 인터페이스를 제공함
  • 해당 인터페이스를 상속받고 제네릭에 엔티티 클래스와 엔티티 클래스가 사용하는 식별자 타입을 지정

12.4 쿼리 메소드 기능

  • 쿼리 메소드 기능 중 대표적으로 메소드 이름만으로 쿼리를 생성하는 기능이 있는데 인터페이스에 메서드만 선언하면 해당 메서드의 이름으로 적절한 JPQL 쿼리를 생성해서 실행한다.
  • 스프링 데이터 JPA가 제공하는 쿼리 메소드 기능은 크게 3가지이다
    • 메소드 이름으로 쿼리 생성
    • 메서드 이름으로 JPA NamedQuery 호출
    • @Query 어노테이션을 사용해서 리포지토리 인터페이스에 쿼리 직접 정의

12.4.1 메서드 이름으로 쿼리 생성

  • 엔티티의 필드명이 변경되면 인터페이스에 정의한 메서드 이름도 꼭 함께 변경해야 한다. 그렇지 않으면 애플리케이션 시작하는 시점에 오류가 발생한다.

12.4.2 JPA NamedQuery

  • JPA NamedQuery는 이름 그대로 쿼리에 이름을 부여해서 사용하는 방법이다.
  • @NamedQuery 어노테이션으로 Named 쿼리를 정의 후 JPA에서 직접 호출해서 사용함.

12.4.3 @Query, 리포지토리 메서드에 쿼리 정의

  • 이 방법은 실행할 메서드에 정적 쿼리를 직접 작성하므로 이름없는 Named 쿼리라 할 수 있다.
  • 또한 JPA Named 쿼리 처럼 애플리케이션 실행 시점에 문법 오류를 발견할 수 있는 장점이 있다.
  • 네이티브 SQL을 사용하려면 @Query어노테이션에 nativeQuery = true를 설정한다.
  • 스프링 데이터 JPA가 지원하는 파라미터 바인딩을 사용하면 JPQL은 위치 기반 파라미터를 1부터 시작하지만 네이티브 SQL은 0부터 시작함

12.4.4 파라미터 바인딩

  • 스프링 데이터 JPA는 위치 기반 파라미터 바인딩과 이름 기반 파라미터 바인딩을 모두 지원한다.
  • 기본값은 위치 기반인데 파라미터 순서로 바인딩한다.
  • 이름 기반 파라미터 바인딩 사용시 @Param 어노테이션 이용

12.4.5 벌크성 수정 쿼리

  • 벌크성 수정, 삭제 쿼리는 @Modifying 어노테이션을 사용한다.
  • 벌크성 쿼리를 실행하고 나서 영속성 컨텍스트를 초기화하고 싶으면 @Modyfying(clearAutomatically = true) 로 설정

12.4.6 반환 타입

  • 결과가 한 건 이상이면 컬렉션 인터페이스를 사용, 단건이면 반환 타입을 지정
  • 조회 결과가 없으면 컬렉션은 빈 컬렉션을 반환, 단건은 null을 반환
  • 단건을 기대하고 반환 타입을 지정했는데 결과가 2건 이상이면 NonUniqueResultException 발생

 

 

12.4.7 페이징과 정렬

  • 스프링 데이터 JPA는 쿼리 메서드에 페이징과 정렬 기능을 사용할 수 있도록 Sort와 Pageable 을 제공함

12.4.8 힌트

  • JPA 쿼리 힌트를 사용하려면 @QueryHints 어노테이션 사용
  • 참고로 SQL힌트가 아니라 JPA 구현체에게 제공하는 힌트이다.
  • forCounting 속성은 반환 타입으로 Page 인터페이스를 적용하면 추가로 호출하는 페이징을 위한 count 쿼리에돟 쿼리 힌트를 적용할지를 설정하는 옵션

12.4.9 Lock

  • 쿼리 시 락을 걸려면 @Lock 어노테이션을 사용한다.

12.5 명세

  • DDD에서 명세(SPECIFICATION)라는 개념을 소개하는데 스프링 데이터 JPA는 JPA Criteria로 이 개념을 사용할 수 있도록 지원
  • 명세를 이해하기 위한 핵심 단어는 술어(predicate)인데 이것은 단순히 참이나 거짓으로 평가된다.
  • AND, OR 같은 연산자로 조합 가능
  • JpaSpeciíicationExecutor 인터페이스를 상속 받으면 사용 가능
  • Specifications는 명세들을 조립할 수 있도록 도와주는 클래스이며 where(), and(), or(), not() 메서드를 제공
  • 명세 정의시 Specification 인터페이스를 구현하면 되며 toPredicate(..) 메서드만 구현하면 된다.

12.6 사용자 정의 리포지토리 구현

  • 리포지토리를 직접 구현 시 공통 인터페이스가 제공하는 기능까지 모두 구현해야하므로 스프링데이터 JPA에서는 이런 문제를 우회해서 필요한 메서드만 구현할 수 있도록 방법 제공
  • 커스텀 리포지토리 인터페이스를 생성 후 사용자 정의 인터페이스를 구현한 클래스 이름 작성 시 인터페이스 이름 + Impl로 지어야 함

12.7 Web 확장

  • 스프링 MVC에서 사용할 수 있는 편리한 기능 제공
  • 식별자로 도메인 클래스를 바로 바인딩해주는 도메인 클래스 컨버터 기능과 페이징과 정렬 기능

12.7.1. 설정

  • 스프링 데이터가 제공하는 Web 확장 기능을 활성화하려면 SpeingDataWebConfiguration을 스프링 빈으로 등록하면 됨
  • @EnableSpringDataWebSupport 어노테이션도 제공

12.7.2 도메인 클래스 컨버터 기능

  • 도메인 클래스 컨버터는 HTTP 파라미터로 넘어온 엔티티의 아이디로 엔티티 객체를 찾아서 바인딩 해줌
  • 도메인 클래스 컨버터는 해당 엔티티와 관련된 리포지토리를 사용해서 엔티티를 찾음
  • 도메인 클래스 컨버를 통해 넘어온 엔티티를 컨트롤러에서 직접 수정해도 실제 데이터베이스에는 반영되지 않는다. 이것은 스프링 데이터와는 관련이 없고 순전히 영속성 컨텍스트의 동작 방식과 관련 있음

12.7.3 페이징과 정렬 기능

  • 페이징과 정렬 기능을 편리하게 사용할 수 있도록 HandlerMethodArgumentResolver 제공
  • 페이징 : PageableHandlerMethodArgumentResolver
  • 정렬 : SortHandlerMethodArgumentResolver
  • 페이징에서 Pageable은 인터페이스며 실제는 PageRequest 객체가 생성됨
  • 만약 사용해야 할 페이징 정보가 둘 이상이면 접두사를 사용해서 구분 가능하며, @Qualifier 어노테이션을 사용해서 구분
  • 페이징 기본 값 변경 시 @PageableDefault 사용

12.8 스프링 데이터 JPA가 사용하는 구현체

  • 스프링 데이터 JPA가 제공하는 공통 인터페이스는 SimpleJpaRepository 클래스가 구현한다
  • 해당 클래스에 어노테이션 중 @Transactional 어노테이션은 JPA의 모든 변경은 트랜잭션 안에서 이루어져야하므로 적용되어 있고 해당 어노테이션은 readOnly = true가 적용되어 있다.

댓글