만약
Spring JPA data를 상속하고 있는 Repository interface를 구현하려고 하려면 이 모든 method들을 구현해야 한다. 그러나 따로 메서드를 빼서 내가 원하는 구현을 하고 싶을 땐 어떻게 해야할까?
ex ) 직접 sql 접근 (JDBC Connection), QueryDsl 사용할 때 쿼리 직접 넣으니까 빼서 구현 등
- custom Interface 생성
public interface MemberRepositoryCustom { List<Member> findMemberCustom(); }
- custom Interface impl 생성
@RequiredArgsConstructor public class MemberRepositoryImpl implements MemberRepositoryCustom{ private final EntityManager em; //직접 sql 접근(jdbc connection 맺거나 JPQL 하면 된다. @Override public List<Member> findMemberCustom() { return em.createQuery("select m from Member m") .getResultList(); } }
- 기존 SpringDataJPA Repository에 custom Interface 상속받는다.
public interface MemberRepository extends JpaRepository<Member,Long>, MemberRepositoryCustom{
- 기존 SpringDataJPA Repository에서 구현된 method를 쓰면 구현체에서 실행된다.
@Test public void callCustom() throws Exception { List<Member> memberCustom = memberRepository.findMemberCustom(); //CustomInterface에 정의됐고, Impl에서 구현한 구현체 }
💥
유의사항 및 실무 팁
핵심 Business 로직이 있는 repository랑
화면에 fit한 Repository를 최대한 분리해야 유지보수, 핵심기능 찾기가 편하다.
그냥 임의의 Repository를 Class로 구현해서 스프링 빈에 등록해서 쓰면 된다.
@Repository
//핵심 비즈니스 로직이 들어있는 기본 SpringDataJPA 인터페이스 Repository
public interface MemberRepository extends JpaRepository<Member,Long>, MemberRepositoryCustom{
List<Member> findByusernameAndAgeGreaterThan(String username, int age);
@Query(name = "Member.findByUsername")
List<Member> findByUsername(@Param("username") String username);
}
//화면과 Fit한 메서드들을 모아 분리해놓은 Repository /Dto로 받아오는 것을 주로 뺀다.
@Repository
@RequiredArgsConstructor
public class MemberQueryRepository {
private final EntityManager em;
public List<Member> findByusernameAndAgeGreaterThan(String username, int age){
return em.createQuery("select m from Member m where m.username = :username and m.age > :age")
.setParameter("username", username)
.setParameter("age", age)
.getResultList();
}
}
Uploaded by Notion2Tistory v1.1.0