4. JpaRepository(공통 Interface) 적용, 분석

민정·2022년 12월 6일
1

Spring Data JPA

목록 보기
4/17
post-thumbnail
post-custom-banner

📘 공통 인터페이스 적용

📁 MemberRepository

JpaRepository interface를 상속받는 새로운 MemberRepository interface를 생성한다.

extends JpaRepository<엔티티, pk타입>

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

✔ MemberRepositoryTest

memberRepository class 출력해보니 proxy 객체임을 확인

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

    @Autowired MemberRepository memberRepository;

    @Test
    public void testMember(){

        System.out.println("memberRepository = " + memberRepository.getClass()); 
  		// class com.sun.proxy.$Proxy121 (스프링 데이터 JPA가 MemberRepository 인터페이스 보고 프록시 객체(구현체)를 만들어서 주입)								
    }


🧐 Q. MemberRepository는 interface인데 구현체를 만들어주지 않아도 되나요?


spring data jpa인터페이스 구현체를 만들어서, injection 해줍니다!

✨ @Repository 생략 가능

MemberRepository@Repository 어노테이션 생략이 가능하다

컴포넌트 스캔Spring Data JPA자동으로 처리

✔ MemberRepositoryTest

MemberJpaRepositoryTest의 basicCRUD에서 순수 JPA를 사용한 레포지토리인 MemberJpaRepositorySpring Data JPA를 사용한 MemberRepository로 변경

😄 그 결과 정상적으로 동작함!

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

    @Autowired MemberRepository memberRepository;
    @PersistenceContext EntityManager em;

    @Test
    public void basicCRUD(){// MemberJpaRepository -> MemberRepository로 변경
        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);

        // 리스트 조회 검증
        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);
    }
  }


📘 공통 인터페이스 분석

📁 JpaRepository

JPA에 특화된 기능을 가진 Interface

package org.springframework.data.jpa.repository;

@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {

	...
}

Spring Data Project라는 공통 프로젝트가 있고, 하위에 Spring Data Jpa, Spring Data Mongo, Spring Data Redis등등이 있다.
org.springframework.data : 공통의 CRUD
org.springframework.data.jpa : JPA 특화 기능

📁 PagingAndSortingRepository

페이징과 정렬에 관련된 기능을 가진 Interface

package org.springframework.data.repository;

@NoRepositoryBean
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {
}

package : org.springframework.data
=> 페이징과 정렬은 관계형 DB, NoSQL, MongoDB... 다 비슷
=> 그래서 모든 DB에 공통적으로 적용되는 공통 인터페이스 제공

📁 CrudRepository

기본적인 CRUD 기능을 가진 interface

package org.springframework.data.repository;

@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {
	<S extends T> S save(S entity);
    
    Optional<T> findById(ID id);
    
    Iterable<T> findAll();
    
    // ... 이외에도 많은 기본적인 CRUD 함수
}

✨ 공통 인터페이스 구성

📌 주요 메서드

T : 엔티티
ID : 엔티티의 PK
S : 엔티티와 그 자식 타입

save(S) 새로운 엔티티 저장, 이미 있는 엔티티는 병합
delete(T) 엔티티 하나 삭제 (내부에서 em.remove() 호출)
findById(ID) 엔티티 하나 조회 (내부에서 em.find() 호출)
getOne(ID) 엔티티를 프록시로 조회 (내부에서 em.getReference() 호출)
findAll(...) 모든 엔티티 조회. 정렬(Sort)나 페이징(Pageable) 조건을 파라미터로 제공할 수 있다.

😄 JpaRepository는 상상할 수 있는 공통 기능을 대부분 제공한다고 생각하면 된다!!



📌 정리

  • Spring Data JPA는 스프링 프레임워크에서 JPA를 편리하게 사용할 수 있도록 지원하는 프로젝트

  • CRUD를 처리하기 위한 JpaRepository라는 공통 Interface 제공

  • 리포지토리 개발할 때 인터페이스만 작성하면, 실행시점에 Spring Data JPA가 구현 객체를 동적으로 생성해서 주입

=> 데이터 접근 계층(repository) 개발할 때, 구현 클래스 없이 interface만 작성해도 개발 완료!



출처

김영한 강사님 - 인프런 실전! 스프링 데이터 JPA

김영한, ⌜자바 ORM 표준 JPA 프로그래밍⌟

post-custom-banner

0개의 댓글