이번 내용은 실무에서 정말 많이 사용한다. querydsl repository를 만들고 활용하기 좋다.
실무에서는 다양한 상황에 맞추어 인터페이스와 메서드를 직접 구현할 필요가 있다.
예를 들어, JPA를 사용하다가 Spring JDBC Template이나 MyBatis 등을 사용해야 할 때가 있다.
Spring Data JPA의 기본 인터페이스만으로는 충분하지 않은 경우, 사용자 정의 리포지토리를 구현하여 해결할 수 있다.
Spring Data JPA가 제공하는 인터페이스를 직접 구현하면 구현해야 하는 기능이 너무 많은데, 어떻게 해야 할까?
구현 절차
1. 사용자 정의 인터페이스 생성
먼저, 구현할 메서드를 추상화한 사용자 정의 인터페이스를 생성한다.
public interface MemberRepositoryCustom {
List<Member> findMemberCustom();
}
2. 사용자 정의 인터페이스 구현
생성한 인터페이스를 실제로 구현한다. 여기서는 JPA의 EntityManager를 사용하여 쿼리를 작성할 수 있다.
@RequiredArgsConstructor
public class MemberRepositoryImpl implements MemberRepositoryCustom{
private final EntityManager em;
// mybatis 등 다른 것들 전부 가능
@Override
public List<Member> findMemberCustom() {
return em.createQuery("select m from Member m").getResultList();
}
}
3. 기존 리포지토리에 사용자 정의 인터페이스 상속
기존의 JPA 리포지토리 인터페이스에 사용자 정의 인터페이스를 상속시킨다.
public interface MemberRepository extends JpaRepository<Member, Long>, MemberRepositoryCustom {
// ...
이것은 Java가 지원하는 것이 아니고, Spring Data JPA가 엮어서 동작하게 도와준다.
명명규칙
이렇게 사용하기 위해선 딱 하나의 규칙을 지켜야한다.
첫 순서로 만든 interface의 이름은 상관없고 이를 직접 구현한 클래스는 'Impl'을 꼭 붙여줘야 한다.
즉, 직접 구현한 클래스의 명명 규칙이 중요한데, '직접 구현한 클래스를 받을 클래스 + Impl'가 이름이 되어야 한다.
상속받는 리포지토리가 MemberRepository이므로, MemberRepositoryImpl로 추가적인 쿼리를 작성하고, 이를 추상화한 인터페이스를 상속받게 하면 되는 것이다.
다시 한번 정리하면
1. 기존에 JpaRepository를 상속받는 인터페이스 MemberRepository 정의
2. 추가적인 기능을 추상화한 Interface (해당 인터페이스는 명명규칙 x) 생성
3. 2번에서 생성한 Interface를 구현할 클래스의 이름은 1번 interface 이름 + 'Impl'로 생성해 주면 되는 것이다.
항상 사용자 정의 리포지토리를 구현해야 하는 것은 아니다. 핵심 비즈니스 로직과 view 단 같은 쿼리들을 사용자 정의 리포지토리가 아닌 아예 다른 클래스로 쪼개는 것이 더 좋다.
ex) MemberQueryRepository라는 클래스 생성 + @Repository로 직접 생성
'JPA > Spring Data JPA' 카테고리의 다른 글
[Spring Data JPA] 7. BaseEntity (1) | 2023.11.24 |
---|---|
[Spring Data JPA] 5. JPA Hint & Lock (0) | 2023.11.23 |
[Spring Data JPA] 4. @EntityGraph (0) | 2023.11.23 |
[Spring Data JPA] 3. 벌크성 수정 쿼리 (0) | 2023.11.23 |
[Spring Data JPA] 2. Spring Data JPA Paging (0) | 2023.11.23 |