스프링 데이터 JPA - 공통 인터페이스(JpaRepository) 기능 생성

2023. 8. 20. 20:43·Back-End/Spring Data JPA

실전! 스프링 데이터 JPA - 인프런 | 강의

 

실전! 스프링 데이터 JPA - 인프런 | 강의

스프링 데이터 JPA는 기존의 한계를 넘어 마치 마법처럼 리포지토리에 구현 클래스 없이 인터페이스만으로 개발을 완료할 수 있습니다. 그리고 반복 개발해온 기본 CRUD 기능도 모두 제공합니다.

www.inflearn.com

순수 JPA 기반 리포지토리 생성

JPA 에서는 변경감지를 통해서 엔티티의 값이 변경 되면, 자동으로 update 쿼리문을 생성해서 DB에 날려주기 때문에, update 쿼리를 생성 할 필요가 없다.

리포지토리 생성

MemberJpaRepositoy

package study.datajpa.repository;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;
import study.datajpa.entity.Member;

import java.util.List;
import java.util.Optional;

@Repository
public class MemberJpaRepository {

    @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);
    }
}

테스트 코드 추가

리포지토리 테스트를 위해 MemberJpaRepositoryTest에 테스트 메서드 추가

@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(findMember1);
        assertThat(findMember2).isEqualTo(findMember2);

        //리스트 조회 검증
        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 deletedCount = memberJpaRepository.count();
        assertThat(deletedCount).isEqualTo(0);
    }

공통 인터페이스 설정

JavaConfig 설정 → 스프링 부트 사용시 생략 가능

@Configuration
@EnableJpaRepositories(basePackages = "study.datajpa.repository")
public class AppConfig {}
  • 스프링 부트 사용시 @SpringBootApplication 위치를 지정해준다.
  • 만약 위치가 달라지면 @EnableJpaRepository 필요

스프링 데이터 JPA가 구현 클래스 대신 생성해준다.

  • 스프링 데이터 JPA에서 org.springframework.data.jpa.repository 를 구현한 클래스는 스캔대상이 되어 클래스를 대신 생성 해줌
  • @Repository 생략 가능 → 컴포넌트 스캔을 스프링 데이터 JPA가 자동으로 처리

적용 해보기

package study.datajpa.repository;

import org.springframework.data.jpa.repository.JpaRepository;  //JpaRepository를 구현함으로서 스캔대상이 된다.
import study.datajpa.entity.Team;

public interface TeamRepository extends JpaRepository<Team, Long> {
}

테스트 코드 작성

package study.datajpa.repository;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.transaction.annotation.Transactional;
import study.datajpa.entity.Member;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

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

    @Autowired
    MemberRepository memberRepository;

    @Test
    public 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());
        assertThat(findMember).isEqualTo(member);
    }

    @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(findMember1);
        assertThat(findMember2).isEqualTo(findMember2);

        //리스트 조회 검증
        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 테스트 코드와 다를게 없지만, MemberRepository 의 의존을 데이터 JPA로 변경하여 잘 동작하는지만 확인하였다. → 동일한 방식으로 동작

공통 인터페이스 분석

변경점

일부 메서드들은 Jpa 버전이 올라감에 따라 다음과 같이 변경 되었다.

  • T findOne(ID) → Optional<T> findById(ID)
  • boolean exists(ID) → boolean existsById(ID)

 

제네릭 타입

T : 엔티티

ID : 엔티티의 식별자 타입

S : 엔티티와 그 자식 타입

 

주요 메서드

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

정리

이번 장에서는 스프링 데이터 JPA가 제공하는 가장 강력한 기능 중 하나인 JpaRepository 인터페이스에 대해서 다루어 봤다.

사용 방법 : 사용하고자 하는 인터페이스에 JpaRepository<엔티티클래스, PK클래스>를 상속받아서 사용 가능하다.

반응형
저작자표시 (새창열림)
'Back-End/Spring Data JPA' 카테고리의 다른 글
  • 데이터 스프링 JPA - 쿼리 메소드 기능(벌크성 수정 쿼리, @EntityGraph, JPA Hint & Lock)
  • 스프링 데이터 JPA - 쿼리 메소드 기능(페이징과 정렬)
  • 스프링 데이터 JPA - 쿼리 메소드 기능(쿼리 메소드 이름, @NamedQuery, @Query)
  • 스프링 데이터 JPA - 프로젝트 환경설정 및 예제 도메인 모델 작성
LightSource
LightSource
어제보단 발전한 오늘의 나를 위한 블로그
    반응형
  • LightSource
    LightSourceCoder
    LightSource
  • 전체
    오늘
    어제
    • 분류 전체보기 (152)
      • Git (4)
      • Language (6)
        • Java (6)
      • Back-End (63)
        • Spring Boot (4)
        • MyBatis (1)
        • Oracle (1)
        • PL SQL (3)
        • JPA (26)
        • Spring Data JPA (5)
        • Spring MVC (8)
        • Spring (12)
        • Spring Security (2)
        • Redis (1)
      • Front-End (38)
        • 아이오닉 (2)
        • JSP (7)
        • JavaScript (4)
        • React (16)
        • TypeScript (3)
        • Angular (6)
      • AWS (1)
      • CI & CD (1)
      • 개발지식 (13)
        • 네트워크 (9)
        • CS 지식 (4)
      • 데이터모델링 (2)
      • Tool (1)
      • 프로젝트 (5)
      • 독후감 (2)
      • 잡생각 (0)
      • 면접 준비 (1)
      • 알고리즘 (14)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    배열요소삭제
    배요소열추가
    배열요소수정
    리액트
    react
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
LightSource
스프링 데이터 JPA - 공통 인터페이스(JpaRepository) 기능 생성
상단으로

티스토리툴바