-
#Spring Data JPA - 10 확장 기능-사용자 정의 리포지토리 구현카테고리 없음 2021. 3. 25. 10:00
사용자 정의 리포지토리 구현
· 스프링 데이터 JPA 리포지토리는 인터페이스만 정의하고 구현체는 스프링이 자동 생성
· 스프링 데이터 JPA가 제공하는 인터페이스를 직접 구현하면 구현해야 하는 기능이 너무 많음
· 다양한 이유로 인터페이스의 메서드를 직접 구현하고 싶다면?(실무에서 굉장히 많이 사용)
· JPA 직접 사용( EntityManager )
· 스프링 JDBC Template 사용
· MyBatis 사용
· 데이터베이스 커넥션 직접 사용 등등...
· Querydsl 사용
만드는 순서
1. 사용자 정의 인터페이스
public interface MemberRepositoryCustom { List<Member> findMemberCustom(); }
SPRING DATA JPA가 아니라 직접 구현한 기능을 쓰고싶은 경우.
구현은 다른 클래스에서했지만 MemberRepository에서 동작을 시키면 SPRING DATA JPA가 다른 곳에 구현되있는것을 호출하게 한다.
- 강사님은 QueryDSL을 쓸대 커스텀해서 많이 사용.
Tip : 간단한건 SPRING DATA JPA를쓰고 복잡한것은 QueryDSL을 쓰자2. 사용자 정의 인터페이스 구현 클래스
@RequiredArgsConstructor public class MemberRepositoryImpl implements MemberRepositoryCustom { private final EntityManager em; @Override public List<Member> findMemberCustom() { return em.createQuery("select m from Member m") .getResultList(); } }
여기서 class Naming규칙이있는데 MmeberRepository + Impl이규칙만 맞추면
findMmeberCustom을 호출했을때 findMmeberCustom을 만든 구현체를 찾아서 호출해준다.3. 사용자 정의 인터페이스 상속
public interface MemberRepository extends JpaRepository<Member, Long>, MemberRepositoryCustom { }
4. 사용자 정의 메서드 호출 코드
List<Member> result = memberRepository.findMemberCustom();
사용자 정의 구현 클래스
· 규칙: 리포지토리 인터페이스 이름 + Impl
· 스프링 데이터 JPA가 인식해서 스프링 빈으로 등록
Impl 대신 다른 이름으로 변경하고 싶으면?
XML 설정
<repositories base-package="study.datajpa.repository" repository-impl-postfix="Impl" />
JavaConfig 설정
@EnableJpaRepositories( basePackages = "study.datajpa.repository", repositoryImplementationPostfix = "Impl" )
참고: 실무에서는 주로 QueryDSL이나 SpringJdbcTemplate을 함께 사용할 때 사용자 정의 리포지토리 기능 자주 사용
findByName or @Query로 해결이 되면 그냥 쓰면되지만 복잡한 동적쿼리를 구현해야할때 사용하자!!!
참고: 항상 사용자 정의 리포지토리가 필요한 것은 아니다.(핵심비지니스 로직이랑 단순하게 화면에 맞춘 쿼리랑 분리하는 게 필요하다.) 그냥 임의의 리포지토리를 만들어도 된다.
예를들어 MemberQueryRepository를 인터페이스가 아닌 클래스로 만들고 스프링 빈으로 등록해서
그냥 직접 사용해도 된다. 물론 이 경우 스프링 데이터 JPA와는 아무런 관계 없이 별도로 동작한다.
왠만하면 유지보수를 위해 관례를 따르고 xml과 javaConfig설정방법은 피하자
사용자 정의 리포지토리 구현 최신 방식
(참고: 강의 영상에는 없는 내용입니다.)
스프링 데이터 2.x 부터는 사용자 정의 구현 클래스에 리포지토리 인터페이스 이름 + Impl 을 적용하는 대신에
사용자 정의 인터페이스 명 + Impl 방식도 지원한다.
예를 들어서 위 예제의 MemberRepositoryImpl 대신에 MemberRepositoryCustomImpl 같이 구현해도 된다.
최신 사용자 정의 인터페이스 구현 클래스 예제
@RequiredArgsConstructor public class MemberRepositoryCustomImpl implements MemberRepositoryCustom { private final EntityManager em; @Override public List<Member> findMemberCustom() { return em.createQuery("select m from Member m") .getResultList(); } }
기존 방식보다 이 방식이 사용자 정의 인터페이스 이름과 구현 클래스 이름이 비슷하므로 더 직관적이다. 추가로 여러 인터페이스를 분리해서 구현하는 것도 가능하기 때문에 새롭게 변경된 이 방식을 사용하는 것을 더 권장한다.