오봉이와 함께하는 개발 블로그
스프링 데이터 JPA - 공통 인터페이스 설정, 적용, 분석 본문
728x90
공통 인터페이스 설정
JavaConfig 설정- 스프링 부트 사용시 생략 가능
@Configuration
@EnableJpaRepositories(basePackages = "jpabook.jpashop.repository")
public class AppConfig {
}
스프링 부트 사용시 @SpringBootApplication
위치를 지정한다.(해당 패키지와 하위 패키지 인식)
만약 위치가 달라지면 @EnableJpaRepositories
가 필요하다.
스프링 데이터 JPA가 구현 클래스 대신 생성
- org.springframework.data.repository.Repository를 구현한 클래스는 스캔 대상이다.
- MemberRepository 인터페이스가 동작한 이유임.
- memberRepository.getClass()로 실제 출력하면 class com.sun.proxy.$ProxyXXX가 나온다.
- @Repository 애노테이션 생략 가능
- 컴포넌트 스캔을 스프링 데이터 JPA가 자동으로 처리
- JPA 예외를 스프링 예외로 변환하는 과정도 자동으로 처리
리포지토리 인터페이스를 보고 스프링 데이터 JPA가 구현 클래스를 만들어서 꽂은 것이다.
즉, 인터페이스만 만들어 놓으면 알아서 스프링 데이터 JPA가 injection 해준다
공통 인터페이스 적용
순수 JPA로 구현한 MemberJpaRepository 대신에 스프링 데이터 JPA가 제공하는 공통 인터페이스 사용해보자.
스프링 데이터 JPA 기반 MemberRepository
public interface MemberRepository extends JpaRepository<Member, Long> {
// <T(Object Type), ID(T의 PK가 어떤 타입인가?)>
}
MemberRepository 테스트
@SpringBootTest
@Transactional
class MemberRepositoryTest {
@Autowired
MemberRepository memberRepository;
@Test
void testMember() {
Member member = new Member("memberA");
Member savedMember = memberRepository.save(member);
Member findMember = memberRepository.findById(savedMember.getId()).get();
assertThat(findMember.getId()).isEqualTo(member.getId());
assertThat(findMember.getUsername()).isEqualTo(member.getUsername());
// 이게 true인 이유는 JPA는 같은 트랜잭션 안에 있는 객체는 동일성을 보장하기 때문이다.
assertThat(findMember).isEqualTo(member);
}
@Test
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);
// 리스트 조회 검증
List<Member> all = memberRepository.findAll();
assertThat(all.size()).isEqualTo(2);
// count 검증
long count = memberRepository.count();
assertThat(count).isEqualTo(2);
// 삭제 검증
memberRepository.delete(member1);
memberRepository.delete(member2);
long deletedCount = memberRepository.count();
assertThat(deletedCount).isEqualTo(0);
}
}
기존 순수 JPA 기반 테스트에서 사용했던 코드를 그대로 스프링 데이터 JPA 리포지토리 기반 테스트로 변경해도 동일한 방식으로 동작한다.
TeamRepository 생성
public interface TeamRepository extends JpaRepository<Team, Long> {
}
TeamRepository는 테스트 생략하자.
- Generic
- T : 엔티티 타입
- ID : 식별자 타입(T의 PK 타입)
공통 인터페이스 분석
- JpaRepository 인터페이스 : 공통 CRUD 제공
- 제네릭은 <엔티티 타입, 식별자 타입> 설정
JpaRepository
공통 기능 인터페이스
public interface JpaRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {
}
JpaRepository
를 사용하는 인터페이스
public interface MemberRepository extends JpaRepository<Member, Long> {
}
공통 인터페이스 구성
최신 스프링 데이터 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) 조건을 파라미터로 제공할 수 있다.
- save(S)
참고로 JpaRepository
는 대부분의 공통 메서드를 제공한다.
인프런 김영한 지식공유자님 강의 : 실전! 스프링 데이터 JPA
728x90
'BE > JPA' 카테고리의 다른 글
스프링 데이터 JPA - JPA NamedQuery (0) | 2022.09.08 |
---|---|
스프링 데이터 JPA - 메소드 이름으로 쿼리 생성 (0) | 2022.09.08 |
스프링 데이터 JPA - 예제 도메인 모델과 동작확인 (0) | 2022.09.07 |
스프링 데이터 JPA - 동작 확인 (0) | 2022.09.07 |
JPA 2 - 스프링 데이터 JPA 소개 (0) | 2022.09.07 |
Comments