1 분 소요

오늘은 JpaRepository 에 대해서 알아보자. JavaConfig 설정 - 스프링 부트 사용 시 생략 가능

1
2
3
4
5
6
@Configuration
@EnableJpaRepositories(basePackages = 
"jpabook.jpashop.reopsitory")
public class Appconfig {
 ...
}

MemberReopository.java

1
2
3
4
5
6
7
package study.datajpa.repository;  
  
import org.springframework.data.jpa.repository.JpaRepository;  
import study.datajpa.entity.Member;  
  
public interface MemberRepository extends JpaRepository<Member, Long> {  
}

이 코드는 인터페이스고 안에 지정된 메서드도 없다. 그저 JpaRepository 인터페이스만 상속 받고 있다.

그런데 어떻게 작동을 할까.테스트 코드에서 한번 찍어보자

1
2
3
4
5
6
7
8
9
10
11
12
13
@SpringBootTest  
@Transactional  
@Rollback(value = false)  
class MemberRepositoryTest {  
  
    @Autowired MemberRepository memberRepository;  
  
    @Test  
    @DisplayName("")  
    void testMember() throws Exception {  
        //given  
        System.out.println("memberRepository = " + memberRepository.getClass());  
    }

무슨 프록시 객체가 찍혀있다. 스프링이 Autowired 하면서 구현체를 인젝션 해버린거다.

JpaRepository를 가보면 엄청나게 많은 메서드들이 정의되어 있다.

그래서

1
2
3
4
5
6
7
package study.datajpa.repository;  
  
import org.springframework.data.jpa.repository.JpaRepository;  
import study.datajpa.entity.Member;  
  
public interface MemberRepository extends JpaRepository<Member, Long> {  
}

이렇게만 작성하면, @Repository, @PersistenceContext 이런 어노테이션이 필요 없고 그냥 사용만 하면된다.

extends JpaRepository<엔티티, 엔티티에 매핑된 PK의 타입> 이렇게 사용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@Autowired MemberRepository memberRepository;

@Test  
@DisplayName("CRUD test")  
void basicCRUD() throws Exception {  
    //given  
    Member member1 = new Member("member1");  
    Member member2 = new Member("member2");  
    memberRepository.save(member1);  
    memberRepository.save(member2);  
  
    //when  
    Member findMember1 = memberRepository.findById(member1.getId()).get();  
    Member findMember2 = memberRepository.findById(member2.getId()).get();  
    //then  
    assertThat(findMember1).isEqualTo(member1);  
    assertThat(findMember2).isEqualTo(member2);  
  
    //리스트 조회 검증  
    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 deletedCount = memberRepository.count();  
    assertThat(deletedCount).isEqualTo(0);  
  
}

아무것도 안만들고 그냥 테스트를 해봐도 잘 통과가 되는 것을 볼 수 있다..

공통 인터페이스 구성

여러 기능들을 가진 인터페이스가 인터페이스를 상속받는데 jpa에 관련된 건 jpa 패키지 내에 있고 공통적인 페이징이나 crud 이런 건 그냥 스프링 데이터 패키지 내에 있다. 이를 통해 뭐 NoSQL 이라던가 jpa를 사용하지 않는 환경에서 페이징 과 같은 기능을 사용할 수도 있을꺼라 생각된다.

주의

  • 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는 대부분의 공통 메서드를 제공한다.

태그: ,

카테고리:

업데이트:

댓글남기기