JpaRepository interface를 상속받는 새로운 MemberRepository interface를 생성한다.
extends JpaRepository<엔티티, pk타입>
public interface MemberRepository extends JpaRepository<Member, Long> {
}
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 인터페이스 보고 프록시 객체(구현체)를 만들어서 주입)
}
spring data jpa
가인터페이스 구현체
를 만들어서,injection
해줍니다!
MemberRepository
에@Repository
어노테이션 생략이 가능하다
컴포넌트 스캔
을 Spring Data JPA
가 자동
으로 처리
MemberJpaRepositoryTest의 basicCRUD에서
순수 JPA
를 사용한 레포지토리인MemberJpaRepository
를Spring 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);
}
}
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 특화 기능
페이징과 정렬에 관련된 기능을 가진 Interface
package org.springframework.data.repository;
@NoRepositoryBean
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {
}
package : org.springframework.data
=> 페이징과 정렬은 관계형 DB, NoSQL, MongoDB... 다 비슷
=> 그래서 모든 DB에 공통적으로 적용되는 공통 인터페이스
제공
기본적인 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만 작성해도 개발 완료
!
김영한, ⌜자바 ORM 표준 JPA 프로그래밍⌟