Spring Data JPA - 공통 인터페이스

2022. 7. 26. 20:33·공부/JPA
반응형

출처 : 인프런 실전! 스프링 데이터 JPA

Spring Data JPA 게시글은 대부분 인프런의 김영한님의 강의인 '실전! 스프링 데이터 JPA' 기반으로 내용을 정리했습니다.

 

공통 인터페이스 설정

원래는 스프링에서는 JavaConfig로 설정해야한다.

@SpringBootApplication
@EnableJpaRepositories(basePackages = "study.datajpa.repository")
public class DataJpaApplication {

   public static void main(String[] args) {
      SpringApplication.run(DataJpaApplication.class, args);
   }

}

스프링 부트에서는 다행히도 생략이 가능하며 @SpringBootApplication가 적용된 파일의 패키지와 하위 패키지를 인식할 수 있다. 만약 위치가 달라지면 @EnableJpaRepositories를 사용하긴 해야한다.

 

MemberRepository.interface

public interface MemberRepository extends JpaRepository<Member, Long> {
}
  • JpaRepository<엔티티, 엔티티의 PK 타입>

저번에 잠깐 생성하고 맛만 봤었던 interface를 다시 한 번 살펴보자. 느낌이 오겠지만 이게 바로 스프링에서 제공하는 스프링 데이터 JPA이다. 이 인터페이스는 JpaRepository를 상속받고 있다. JpaRepository 안에 소스를 들여다보면 역시 interface라 구현체가 없다. 구현체가 없는데 어떻게 기능이 동작할까? 

MemberRepositoryTest.class

전에 생성했었던 테스트 파일에 memberRepository의 정체를 출력해보자.

@SpringBootTest
@Transactional
@Rollback(false)
class MemberRepositoryTest {

    @Autowired MemberRepository memberRepository;

    @Test
    public void testMember() {

        // memberRepository의 정체
        System.out.println("memberRepository = " + memberRepository.getClass());

        //... 생략
    }
}
// 출력 로그 중 일부
memberRepository = class com.sun.proxy.$Proxy117

스프링이 인터페이스를 보고 스프링 데이터 JPA에서 구현 클래스를 만들어 주입을 해준 것이다.

 

Spring Data JPA 구현 클래스 생성

  • 'org.springframework.data.repository.Repository'를 구현한 클래스는 스캔 대상
    • MemberRepository가 동작한 이유
    • 실제 출력해보기(Proxy)
    • memberRepository.getClass() -> class com.sun.proxy.$ProxyXXX
  • @Repository 애노테이션 생략 가능
    • 컴포넌트 스캔을 스프링 데이터 JPA가 자동으로 처리
    • JPA 예외를 스프링 예외로 변환하는 과정도 자동으로 처리함

 

예제

  • 전 포스팅에서 만들었던 TeamRepository.class 이름을 TeamJpaRepository.class로 변경
  • TeamRepository.interface 생성
public interface TeamRepository extends JpaRepository<Team, Long> {
}

 


 

공통 인터페이스 적용(테스트)

MemberRepositoryTest.class

@SpringBootTest
@Transactional
@Rollback(false)
class MemberRepositoryTest {

    @Autowired MemberRepository memberRepository;
    
    // ... 생략

    @Test
    public void basicCRUD() {
        Member member1 = new Member("member1");
        Member member2 = new Member("member2");
        memberRepository.save(member1);
        memberRepository.save(member2);

        // 단건 조회 검증
        Member findMember1 = memberRepository.findById(member1.getId()).get();
        Member findMember2 = memberRepository.findById(member2.getId()).get();
        assertThat(findMember1).isEqualTo(member1);
        assertThat(findMember2).isEqualTo(member2);

        findMember1.setUsername("member!!!!!!!!!!");

        // 리스트 조회 검증
        List<Member> all = memberRepository.findAll();
        assertThat(all.size()).isEqualTo(2);

        // 카운트 검증
        long count = memberRepository.count();
        assertThat(count).isEqualTo(2);

        // 삭제 검증
        memberRepository.delete(member1);
        memberRepository.delete(member2);
        long deleteCount = memberRepository.count();
        assertThat(count).isEqualTo(2);
    }
}

MemberJpaRepository.class에서 만들었던 테스트를 가지고 와서 memberJpaRepository를 memberRepository로 수정해주고 돌려주면 테스트가 통과하는 걸 볼 수 있다. repository만 수정한 건데 왜 통과되냐면 애초에 MemberJpaRepository.class에서의 테스트 코드(findById, findAll 등)를 스프링 데이터 JPA에서 제공하는 기능의 이름과 맞췄기 때문이다.

 


 

공통 인터페이스 분석

이렇게 쉽게 코드를 작성할 수 있게 해주는 JpaRepository 인터페이스의 정체는 무엇일까? 한 번 속을 까보자.

  • JpaRepository 인터페이스 : 공통 CRUD 제공
  • 제네릭은<엔티티 타입, 식별자 타입>이다.

 

JpaRepository 공통 기능 인터페이스

public interface JpaRepository<T, ID> 
	extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T>
{
...
}

 

JpaRepository를 사용하는 인터페이스

public interface MemberRepository extends JpaRepository<Member, Long> {
}

 

공통 인터페이스 구성

  • 주의
    • T findOne(ID) → Optional<T> findById(ID) 변경
  • 제네릭 타입
    • T : 엔티티
    • ID : 엔티티의 식별자 타입
    • S : 엔티티와 그 자식 타입
  • 주요 메서드
    • save(S) : 새로운 엔티티는 저장하고 이미 있는 엔티티는 병합한다.
    • delete(T) : 엔티티 하나를 삭제. 내부에서 EntityManager.remove()를 호출한다.
    • findById(ID) : 엔티티 하나 조회. 내부에서 EntityManager.find()를 호출한다.
    • getOne(ID) : 엔티티를 프록시로 조회. 내부에서 EntityManager.getReference() 호출
    • findAll(...) : 모든 엔티티 조회. 정렬(Sort)이나 페이징(Pageable) 조건을 파라미터로 제공할 수 있다.
  • 참고!
    • JpaRepository는 대부분의 공통 메서드를 제공한다.
반응형
저작자표시 비영리 변경금지 (새창열림)
'공부/JPA' 카테고리의 다른 글
  • Spring Data JPA - JPA NamedQuery
  • Spring Data JPA - 메서드 이름으로 쿼리 생성
  • Spring Data JPA - 순수 JPA 기반 리포지토리 만들기
  • Spring Data JPA - 예제 도메인 모델과 동작확인
데부한
데부한
어차피 할 거면 긍정적으로 하고 싶은 개발자
    반응형
  • 데부한
    동동이개발바닥
    데부한
  • 전체
    오늘
    어제
    • 분류 전체보기 (307)
      • 방통대 컴퓨터과학과 (27)
        • 잡담 (9)
        • 3학년1학기 (17)
      • 프로젝트 및 컨퍼런스 회고 (1)
        • 프로젝트 (4)
        • 한이음 프로젝트 (0)
        • 회고 (3)
      • 공부 (165)
        • Spring (37)
        • JPA (71)
        • 인프런 워밍업 클럽_BE (10)
        • Java (6)
        • React.js (27)
        • 넥사크로 (11)
        • 기타 (3)
      • 알고리즘 (85)
        • 알고리즘 유형 (10)
        • 알고리즘 풀이 (57)
        • SQL 풀이 (18)
      • 에러 해결 (13)
      • 잡담 (7)
        • 국비교육 (2)
        • 구매후기 (5)
        • 진짜 잡담 (0)
  • 블로그 메뉴

    • Github
    • Linkedin
    • 홈
    • 방명록
    • 글쓰기
    • 관리
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Spring
    MSA
    JPA
    자바스크립트
    인프런
    egov
    토비의스프링부트
    QueryDSL
    에러해결
    react
    SpringBoot를 이용한 RESTful Web Service 개발
    RESTful
    SQL
    백준
    코딩테스트
    개발자
    oracle
    기출문제
    방통대
    스프링부트
    프로그래머스
    IT
    알고리즘
    운영체제
    springboot
    프론트엔드
    넥사크로
    토이프로젝트
    전자정부프레임워크
    Java
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
데부한
Spring Data JPA - 공통 인터페이스
상단으로

티스토리툴바