computer_study

[JPA] 12. 스프링 데이터 JPA 본문

스터디/자바 ORM표준 JPA 프로그래밍

[JPA] 12. 스프링 데이터 JPA

knowable 2022. 9. 26. 02:53

1. 스프링 데이터 JPA 소개

  • 스프링 프레임워크에서 JPA를 편리하게 사용할 수 있도록 지원하는 프로젝트
  • CRUD처리를 위한 공통 인터페이스를 제공
  • 인터페이스 작성만 하면 실행 시점에 "스프링 데이터 JPA"가 구현 객체를 동적으로 생성해서 주입해준다.
    (데이터 접근 계층 구현 없이 인터페이스만 작성해도 개발을 완료할 수 있다.)
// JPA의 반복적인 CURD
public class MemberRepositroy {
    @PersistenceContext
    EntityManager em;
    
    public void save(Member member) {...}
    public Member findOnd(Long id) {...}
    public List<Member> findAll() {...}
    
    public Member findByUsername(String username) {...}
}
public class ItemRepositroy {
    @PersistenceContext
    EntityManager em;
    
    public void save(Item item) {...}
    public Member findOnd(Long id) {...}
    public List<Member> findAll() {...}
}
// 하는 일이 비슷하게 코드를 작성한다
// GenericDAO를 만들어 상속을 사용할 수도 있지만, 부모에 종속되는 단점이 있다.

////////
// 스프링 데이터 JPA 적용
public interface MemberRepositroy extends JpaRepository<Member, Long>{
    Member findByUsername(String username;)
}
public interface ItemRepositroy extends JpaRepository<Item, Long>{
}

 

2. 스프링 데이터 JPA 설정

  • spring-data-jpa 라이브러리 사용
  • 환경설정 완려 시 스프링 데이터 JPA는 app실행 시 basePackage에 있는 레포지토리 인터페이스들을 찾아서 해당 인터페이스를 구현한 클래스를 동적으로 생성한다음 빈으로 등록한다.
  • 개발자가 직접 구현 클래스를 만들 필요가 없어진다.

 

3. 공통 인터페이스 기능

  • 간단한 CRUD기능을 처리하는 JpaRepositroy 인터페이스 제공
  • 스프링 데이터가 사용하는 인터페이스에 추가적으로 JPA에 특화된 기능을 제공하는 것.

4. 쿼리 메소드 기능

1.메소드 이름으로 쿼리 생성

interface에 findByEmailAndNmae(String email, String name) 정의 후 실행 시

스프링 데이터 JPA는 메소드 이름을 분석해서 아래 JPQL을 생성하고 실행한다

select m from Member m where m.email = ?1 and m.name = ?2

 

엔티티 필드명이 변경된다면 인터페이스에 정의한 메소드 이름을 함께 변경해야 한다.

정해진 규칙에 따라서 이름을 지어야 한다.

 

2.JPA NamedQuery

  • 메소드 이름으로 JPA Named 쿼리를 호출하는 기능을 제공한다. (쿼리에 이름을 부여해서 사용)
// 쿼리 정의 (애노테이션) , XML에 정의도 가능
@Entity
@NamedQuery(
    name = "Member.findByUsername",
    query = "select m from Member m where m.username = :username")
public class Member {
...
}

// 사용 방법. 메소드 이름만으로 호출 가능
public interface MemberRepository extends JpaRepository<Member, Long>{
    List<Member> findByUsername(@Param("username") String username);
}

 

3.@Query, 레포지토리 메소드에 쿼리 정의

레포지토리 메소드에 직접 쿼리를 정의

public interface MemberRepository extends JpaRepository<Member, Long>{
    @Query("select m from Member m where m.username = ?1")
    Member findByUsername(String username);
}
  • 정적 쿼리를 직접 작성하므로 이름 없는 Named 쿼리라 본다
  • 애플리케이션 실행 시점에 문법 오류를 발견할 수 있는 장점이 있다.

 

 

- 파라미터 바인딩

  • 스프링 데이터 JPA는 위치 기반 파라미터 바인딩, 이름 기반 파라미터 바인딩 모두 지원
  • 코드 가독성과 유지보수를 위해 이름 기반 파라미터 바인딩 사용을 추천

- 벌크성 수정 쿼리

  • @Modifying 사용
  • 벌크성 수정 쿼리 -> 대량의 데이터들을 쿼리를 통해 수정
  • 실행 이후 영속성 컨텍스트를 초기화 하고싶다면 clearAutomatically = true로 옵션을 주면 된다.

- 반환 타입

  • 결과가 한 건 이상이면 컬렉션 인터페이스를 사용
  • 단건이면 반환 타입을 지정 -> 2건 이상 조회 시 NonUniqueResultException 발생
  • 조회 결과가 없으면 빈 컬렉션을 반환하고 단건은 null을 반환(원래 NoResultException을 반환하지만 다루기가 어려우므로, 스프링 데이터 JPA는 null을 반환한다.)

- 페이징과 정렬

  • Sort로 정렬, Pageable로 페이징 사용 가능.
  • Page 인터페이스는 다양한 메소드를 지원한다.
Page<Member> findByName(String name, Pageable pageable);
List<Member> findByName(String name, Pageable pageble);
List<Member> findByName(String name, Sort sort);

- 힌트

  • @QueryHints 사용
  • JPA구현체에서 제공하는 힌트

- Lock

  • @Lock을 사용하는데, 이는 16장에서 다룸

5. 명세(specification)

  • 검색하기 위한 제약 조건들을 정의한 클래스
  • JPA는 JPA Criteria로 이 개념을 사용할 수 있도록 지원한다. (10.3절)
  • 여러 Specification을 조합할 수 있다.
  • Specification 인터페이스를 구현해서 명세를 정의할 수 있다.

6. 사용자 정의 리포지토리 구현

  • 스프링 데이터 JPA는 공통기능을 모두 구현할 필요 없이 메소드를 직접 구현할 수 있도록 해준다.
  • 방법
    • 직접 구현 할 메소드를 위한 사용자 정의 인터페이스 작성
    • 사용자 정의 인터페이스를 구현한 클래스 작성 (인터페이스 이름 + Impl로 이름을 짓는다.)
    • 레포지토리 인터페이스에서 사용자 정의 인터페이스를 상속
// 1
public interface MemberRepositoryCustom {
    public List<Member> findMemberCustom();
}
// 2
public class MemberRepositoryImpl implements MemberRepositoryCustom {
    @Override
    public List<Member> findMemberCustom(){
        // 사용자 구현
    }
}
// 3
public interface MemberRepository extends JpaRepository<Member, Long>, MemberRepositoryCustom{
}

 

7. web확장

  • @EnableSpringDataWebSupport로 Web확장 기능 활성화 가능 (스프링 MVC에서 사용할 수 있는 기능 제공)
  • 기능
    • 도메인 클래스 컨버터 기능
      • HTTP 파라미터로 넘어온 엔티티의 아이디로 객체를 찾아서 바인딩 해준다
    • 페이징과 정렬 기능
      • PageableHandlerMethodArgumentResolver -> 페이징 기능
      • SortHandlerMethodArgumentResolver -> 정렬 기능
      • 접두사
        • 페이징 정보가 둘 이상일 때 @Qualifier 사용해서 구분할 수 있다 ( "{접두사명}_" )
        • @Qualifier("member") pageable memberPageable
        • @Qualifier("order") pageable orderPageable
        • /members?member_page=0&order_page=1
      • 기본값
        • page = 0, size= 20이 기본 값
        • @PageableDefault 사용해서 변경 가능

 

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

SimpleJpaRepository class로 구현한다.

 

9. JPA 샵에 적용

10. 스프링 데이터 JPA와 QueryDSL 통합

QueryDSL - SQL, JPQL을 코드로 작성할 수 있도록 도와주는 빌더 API

  • QueryDslPredicateExecutor 상속 사용
    • 스프링 데이터 JPA에서 편리하게 QueryDSL을 사용할 수 있게 해주지만 기능적 한계가 있다.
    • 다양한 기능을 사용하기 위해선 JPAQuery를 직접 사용하거나 스프링 데이터 JPA가 제공하는 QueryDslRepositorySupport를 사용해야 한다.
  • QueryDslRepositorySupport 상속 사용
    • 검색 조건에 따라 동적으로 쿼리를 생성한다.

 

 

 

 

Comments