Spring Data JPA에서 Repository는 인터페이스만 정의하고 구현체는 스프링이 자동으로 생성한다.
만약 Spring Data JPA가 제공하는 인터페이스를 직접 구현하려고 한다면 구현해야 하는 기능들이 너무 많아 오히려 비효율적이다.
그렇다면 다양한 이유로 인터페이스의 메서드를 직접 구현하고 싶다면 어떻게 하면 될까?
대표적인 방법들은 아래와 같다.
- JPA로 직접 구현 (EntityManager)
- Spring JDBC Template 사용
- Mybatis 사용
- 데이터베이스 커넥션 직접 사용...등
- QueryDSL 사용.
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가지 방법 중 하나를 사용하면 된다.
<repositories base-package="study.datajpa.repository"
repository-impl-postfix="Impl" />
@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();
}
}
실무에서는 주로 QueryDSL이나 SpringJdbcTemplate를 함께 사용 할 때 사용자 정의 리포지토리 기능을 자주 사용한다고 한다.