Yebali

Spring Data JPA의 사용자 정의 Repository 본문

Spring

Spring Data JPA의 사용자 정의 Repository

예발이 2021. 10. 11. 21:39
List<Member> result = memberRepository.findMemberCustom();

Spring Data JPA에서 Repository는 인터페이스만 정의하고 구현체는 스프링이 자동으로 생성한다.
만약 Spring Data JPA가 제공하는 인터페이스를 직접 구현하려고 한다면 구현해야 하는 기능들이 너무 많아 오히려 비효율적이다.
그렇다면 다양한 이유로 인터페이스의 메서드를 직접 구현하기 위한 대표적인 방법들은 아래와 같다.

  1. JPA로 직접 구현 (EntityManager)
  2. Spring JDBC Template 사용.
  3. Mybatis 사용.
  4. 데이터베이스 커넥션 직접 사용
  5. QueryDSL 사용.

그중 JPA로 직접 구현하는 방법은 아래와 같다.

JPA로 직접 구현

사용자 정의 인터페이스

public interface MemberRepositoryCustom {
	List<Member> findMemberCustom();
}

사용자 정의 인터페이스 구현 클래스

@RequiredArgsConstructor
// MemberRepository(리포지토리 인터페이스 이름) + Impl
public class MemberRepositoryImpl implements MemberRepositoryCustom {
    
    private final EntityManager em;
    
    @Override
    public List<Member> findMemberCustom() {
        return em.createQuery("select m from Member m")
                .getResultList();
    }
}

사용자 정의 인터페이스를 상속

public interface MemberRepository
        extends JpaRepository<Member, Long>, MemberRepositoryCustom {
}

사용자 정의 메서드 사용

List<Member> result = memberRepository.findMemberCustom();

참고

사용자 정의 구현 클래스의 이름은 "레포지토리 인터페이스 이름 + Impl"로 해야하는 규칙이 있다.
그래야 Spring Data JPA가 인식해서 Spring Bean으로 등록하여 관리해준다.

만약 Impl대신 다른 이름으로 변경하고 싶다면 아래 2가지 방법 중 하나를 사용하면 된다.

  • XML 설정
    <repositories base-package="study.datajpa.repository"
                    repository-impl-postfix="Impl" />​
  • Java Config 설정
    @EnableJpaRepositories(basePackages = "study.datajpa.repository",
                               repositoryImplementationPostfix = "Impl")​

Spring Data 2.x부터는 구현 클래스에 "리포지토리 인터페이스 이름 + Impl" 대신
"사용자 정의 인터페이스 명 + Impl" 방식도 지원한다.
즉, "MemberRepositoryImpl" 대신에 "MemberRepositoryCustomImpl" 같이 구현해도 된다.

@RequiredArgsConstructor
// MemberRepositoryCustom(사용자 정의 인터페이스 명) + Impl
public class MemberRepositoryCustomImpl implements MemberRepositoryCustom {
    
    private final EntityManager em;
        
    @Override
    public List<Member> findMemberCustom() {
        return em.createQuery("select m from Member m")
                .getResultList();
    } 
}