스프링 데이터 JPA 리포지토리는 인터페이스가 구현만 되어있고 모두 상속을 받아야 하기 때문에 현실적이지 않다.
스프링 데이터 JPA가 아니라 JDBC를 직접 활용을 해서 기능을 쓴다거나 MyBatis library 기능을 쓴다거나 완전히 다른 Repository 기능을 쓰고 싶을 때 이런걸 쓸 수 있게 열어놓은 것이 사용자 정의 리포지토리 구현이다.
다양한 이유로 인터페이스의 메서드를 직접 구현하고 싶으면
- JPA 직접 사용( EntityManager )
- 스프링 JDBC Template 사용
- MyBatis 사용
- 데이터베이스 커넥션 직접 사용 등등...
- Querydsl 사용하면 된다.
그리고 여러 커스텀 기능을 스프링 데이터 JPA가 제공해주는 것을 알고 코드를 작성해보자.
// MemberRepositoryCustom
package study.datajpa.repository;
import study.datajpa.entity.Member;
import java.util.List;
public interface MemberRepositoryCustom {
List<Member> findMemberCustom();
}
// MemberRepositoryImpl
@RequiredArgsConstructor
public class MemberRepositoryImpl implements MemberRepositoryCustom{
private final EntityManager em;
// @RequiredArgsConstructor 인해 생략가능
// public MemberRepositoryImpl(EntityManager em) {
// this.em = em;
// }
@Override
public List<Member> findMemberCustom() {
return em.createQuery("select m from Member m")
.getResultList();
}
MemberRepository Interface 에다가 아래와 같이 설정을 해주자.
public interface MemberRepository extends JpaRepository<Member, Long>, MemberRepositoryCustom {
아래처럼 해서 test를 돌리면
@Test
public void callCustom() {
List<Member> result = memberRepository.findMemberCustom();
}
Member를 그대로 찍어온다.
select
member0_.member_id as member_i1_0_,
member0_.age as age2_0_,
member0_.tema_id as tema_id4_0_,
member0_.username as username3_0_
from
member member0_
여기에서 구현된것이
// MemberRepositoryCustom Interface
public interface MemberRepositoryCustom {
List<Member> findMemberCustom();
}
정확하게 실행이 된 것을 확인할 수 있다.
// MemberRepositoryImpl Class
@Override
public List<Member> findMemberCustom() {
return em.createQuery("select m from Member m")
.getResultList();
}
규칙이 있는데
MemberRepositoryImpl에서 아래 MemberRepositoryImpl 명칭을 맞춰줘야 한다.
// MemberRepositoryCustom
@RequiredArgsConstructor
public class MemberRepositoryImpl implements MemberRepositoryCustom{
즉 MemberRepository Interface에서 MemberRepository 뒤에 Impl붙여 MemberRepositoryImpl 규칙을 맞춰줘야 한다.
// MemberRepository Interface
public interface MemberRepository extends JpaRepository<Member, Long>, MemberRepositoryCustom {
그러면 이제 findMemberCustom 구현체로
// MemberRepositoryTest
@Test
public void callCustom() {
List<Member> result = memberRepository.findMemberCustom();
}
MemberRepositoryCustom Interface를 상속한
package study.datajpa.repository;
import study.datajpa.entity.Member;
import java.util.List;
public interface MemberRepositoryCustom {
List<Member> findMemberCustom();
}
MemberRepositoryImpl을 찾아서 호출해준다.
@Override
public List<Member> findMemberCustom() {
return em.createQuery("select m from Member m")
.getResultList();
}
참고사항을 보면 아래와 같다.
- 실무에서 주로 QueryDSL 이나 SpringJdbcTemplate을 함께 사용할 때 사용자 정의 리포지토리 기능 자주 사용가능하다.
- 항상 사용자 정의 리포지토리가 필요한 것은 아니고 임의의 리포지토리를 생성해도 괜찮다.
- 아래의 코드 예시를 보자.
Interface가 아닌 Class로 MemberQueryRepository를 만들고 스프링 빈으로 등록해서 직접 사용해도 된다.
이럴 경우 스프링 데이터 JPA와는 관계없이 별도로 동작한다.
package study.datajpa.repository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import study.datajpa.entity.Member;
import javax.persistence.EntityManager;
import java.util.List;
@Repository
@RequiredArgsConstructor
public class MemberQueryRepository {
private final EntityManager em;
List<Member> findAllMembers() {
return em.createQuery("select m from Member m")
.getResultList();
}
}
사용하는 클라이언트 코드를 MemberRepositoryTest라고 하면 아래와 같이 Autowired를 MemberQueryRepository에다가 설정을 해준다.
@Rollback(false)
class MemberRepositoryTest {
@Autowired MemberRepository memberRepository;
@Autowired TeamRepository teamRepository;
@PersistenceContext
EntityManager em;
@Autowired
MemberQueryRepository memberQueryRepository;
<출처 김영한: 실전! 스프링 데이터 JPA >
'Spring > SpringDataJPA' 카테고리의 다른 글
스프링 데이터 JPA 구현체 분석 (0) | 2022.04.18 |
---|---|
Web 확장 - 도메인 클래스 컨버터 & 페이징과 정렬 (0) | 2022.04.18 |
JPA Hint & Lock (0) | 2022.04.17 |
@EntityGraph (0) | 2022.04.17 |
벌크성 수정 쿼리(error 해결중) (0) | 2022.04.17 |