스프링 데이터 JPA가 제공하는 공통 인터페이스 기능에 대하여 알아보자.
위 순서대로 진행하겠다.
비교를 하기 위해 먼저 지난 시간에 만들어뒀던 순수 JPA 기반 리포지토리를 수정하겠다.
✔️ MemberJpaRepository.java
클래스
@Repository
public class MemberJpaRepository {
// Jpa를 사용하기 위해서는 EntityManager가 필요함
// @PersistenceContext를 사용하면 엔티티 매니저를 가져다줌
@PersistenceContext
private EntityManager em;
public Member save(Member member) {
// 멤버 저장 후 반환
em.persist(member);
return member;
}
public void delete(Member member) {
em.remove(member);
}
public List<Member> findAll() {
return em.createQuery("select m from Member m", Member.class)
.getResultList();
}
public Optional<Member> findById(Long id) {
Member member = em.find(Member.class, id);
return Optional.ofNullable(member);
}
public long count() {
return em.createQuery("select count(m) from Member m", Long.class)
.getSingleResult();
}
public Member find(Long id) {
return em.find(Member.class, id);
}
}
삭제 / 전체 조회 / 단건 조회 / 카운트 기능을 추가하였다.
이제 팀 리포지토리를 만들어보자.
✔️ TeamJpaRepository.java
클래스
@Repository
public class TeamJpaRepository {
@PersistenceContext
EntityManager em;
public Team save(Team team) {
em.persist(team);
return team;
}
public void delete(Team team) {
em.remove(team);
}
public List<Team> findAll() {
return em.createQuery("select t from Team t", Team.class)
.getResultList();
}
public Optional<Team> findById(Long id) {
Team team = em.find(Team.class, id);
return Optional.ofNullable(team);
}
public long count() {
return em.createQuery("select count(t) from Team t", Long.class)
.getSingleResult();
}
}
모든 기능이 회원 리포지토리와 매우 비슷하다.
✔️ MemberJpaRepositoryTest.java
@Test
public void basicCRUD() {
// 멤버 생성
Member member1 = new Member("member1");
Member member2 = new Member("member2");
memberJpaRepository.save(member1);
memberJpaRepository.save(member2);
// 단건 조회 검증
Member findMember1 = memberJpaRepository.findById(member1.getId()).get();
Member findMember2 = memberJpaRepository.findById(member2.getId()).get();
assertThat(findMember1).isEqualTo(member1);
assertThat(findMember2).isEqualTo(member2);
// 리스트 조회 검증
List<Member> all = memberJpaRepository.findAll();
assertThat(all.size()).isEqualTo(2);
// 카운트 검증
long count = memberJpaRepository.count();
assertThat(count).isEqualTo(2);
// 회원 삭제 검증
memberJpaRepository.delete(member1);
memberJpaRepository.delete(member2);
long deleteCount = memberJpaRepository.count();
assertThat(deleteCount).isEqualTo(0);
}
지난 시간에 만들어뒀던 순수 JPA 기반 리포지토리 테스트에 CRUD 기능을 테스트하는 코드를 추가하였다.
잘 동작한다.
이제 순수 JPA로 구현한 MemberJpaRepository
대신, 지난 시간에 생성했던 스프링 데이터 JPA가 제공하는 공통 인터페이스 MemberRepository
를 사용해서 테스트 해보겠다.
✔️ MemberRepositoryTest
@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);
// 리스트 조회 검증
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(deleteCount).isEqualTo(0);
}
순수 JPA 기반 리포지토리 테스트와 매우 비슷하지만 이번에는 스프링 데이터 JPA가 제공하는 인터페이스를 사용하고 있다.
결과는 역시나 성공이다.
어떻게 이런 결과가 나오는지 이제부터 자세히 살펴보자.
MemberRepository
인터페이스가 상속받고 있는 JpaRepository
인터페이스를 살펴보자.
JpaReopository
인터페이스는 PagingAndSortingRepository
인터페이스를 상속받고 있고,
PagingAndSortingRepository
인터페이스는 CrudReopository
인터페이스를,
CrudReopository
인터페이스는 Repository
인터페이스를 상속받고 있다.
➡️ 최상위 Repository
인터페이스
스프링 데이터는 공통 부분을 제공하고, 스프링 데이터 JPA는 JPA에 특화된 기능을 제공한다.
JpaRepository
는 개발자들이 생각할 수 있는 대부분의 공통 메서드를 제공한다고 보면 된다.
📌 최근에
T findOne(ID)
➡️Optional<T> findById(ID)
로 변경되었다.
주요 메소드를 간단히 살펴보자.
save(S)
merge
기능 함께 제공)delete(T)
EntityManager.remove()
메소드를 호출한다.findById(ID)
EntityManager.find()
메소드를 호출한다.getOne(ID)
EntityManager.getReference()
메소드를 호출한다. findAll(...)
Sort
)이나 페이징(Pageable
) 조건을 파라미터로 제공할 수 있다.