본문 바로가기
Java/Spring입문

Spring 입문(15) 스프링 DB 접근 기술: 스프링 데이터 JPA

by 이쟝 2023. 5. 5.
인프런의 김영한님의 스프링입문 강의를 듣고 정리한 내용입니다.
스프링 입문 강의
1. H2 데이터베이스 설치
2. 순수 Jdbc(스프링 통합테스트)
3. 스프링 Jdbc Template
4. JPA
5. 스프링 데이터 JPA

5. 스프링 데이터 JPA

- 스프링 부트와 JPA만 사용해도 개발 생산성이 많이 증가하고, 개발해야 할 코드도 확연히 줄어든다. 여기에 스프링 데이터 JPA를 사용하면, 레포지터리에 구현 클래스 없이 인터페이스만으로 개발을 할 수가 있다.
- 이제까지 반복해온 기본 CRUD 기능도 스프링 데이터 JPA가 모두 제공한다.
- 스프링 부트와 JPA라는 기반 위에, 스프링 데이터 JPA라는 프레임워크를 더하면 지금까지 단순하고 반복이라 생각했던 개발코드들이 줄어들면서 개발자는 핵심 비즈니스 로직을 개발하는데 집중할 수 있다. 
- 스프링 데이터 JPA는 JPA를 편리하게 사용하도록 도와주는 기술로 JPA를 먼저 학습한 후에 스프링 데이터 JPA를 학습해야 한다.

 

  • 스프링 데이터 JPA를 사용하기 위해서는 JPA설정을 그대로 사용한다.

5-1. repository 폴더에 SpringDataJpaMemberRepository 인터페이스 파일을 생성한다. 

src > main > java > hello > hellospring > repository > SpringDataJpaMemberRepository 인터페이스
package hello.hellospring.repository;

import hello.hellospring.domain.Member;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

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

    @Override
    Optional<Member> findByName(String name);
}
- SpringDataJpaMemberRepository 인터페이스는 스프링 데이터 JPA에서 제공하는 JpaRepository를 상속받는다.
- 이때 저장되는 Member 클래스와 pk의 type인 Long을 명시해주고, JpaRepository와 같이 MemberRepository도 상속받는다.(, 로 구분해서 다중 상속)
- 스프링 데이터 JPA가 JpaRepository를 확장하면, 구현체를 자동으로 만들어 Bean에 등록 -> 가져다 사용한다.

- findByName( )만 인터페이스를 생성해주면 구현체를 만들 필요가 없다!

5-2. SpringConfig파일을 SpringDataJpaMemberRepository를 사용할 수 있게 스프링 설정을 변경한 뒤에 통합 테스트를 실행한다.

src > main > java > hello > hellospring > SpringConfig
package hello.hellospring;

//import hello.hellospring.repository.JdbcMemberRepository;
//import hello.hellospring.repository.JdbcTemplateMemberRepository;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
//import javax.sql.DataSource;

@Configuration
public class SpringConfig {

    //private final DataSource dataSource;
    //@Autowired
    //public SpringConfig(DataSource dataSource){
    //    this.dataSource = dataSource;
    //}
    //private final EntityManager em;
    //@Autowired
    //public SpringConfig(EntityManager em){
    //    this.em = em;
    //}

    private final MemberRepository memberRepository;

    @Autowired
    public SpringConfig(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    @Bean
    public MemberService memberService(){
        return new MemberService(memberRepository);
    }

    //@Bean
    //public MemberRepository memberRepository(){
        //return new MemoryMemberRepository();
        //return new JdbcMemberRepository(dataSource);
        //return new JdbcTemplateMemberRepository(dataSource);
        //return new JpaMemberRepository(em);
    //}
}
- 레포지터리의 구현체를 만들지 않았기 때문에 생성할 필요가 없고, 스프링 부트가 실행할 때 스프링 컨테이너에서 MemberRepository를 가져와 MemberService에 이를 주입한다.
- 스프링 데이터 JPA가 SpringDataJpaMemberRepository를 스프링빈에 자동 등록해준다.
- 통합테스트를 실행하면 잘 동작하는 것을 확인할 수 있다.

인터페이스만을 생성해 동작이 가능한 이유는? 

  • 인터페이스를 생성할 때 JpaRepository를 extends 했기 때문이다.
  • 해당 인터페이스를 내려받으면 spring data JPA에서 자동으로 인터페이스의 구현체를 만들고, 스프링 빈으로 자동 등록한다.
  • 개발자는 자동으로 회원 레포지터리 스프링 빈을 SpringConfig에서 MemberService에 주입하고 이를 사용한 것이다. 

스프링 데이터 JPA 제공 클래스

 

- 인터페이스를 생성할 때 상속받은 JpaRepository는 PagingAndSortingRepository인터페이스를 상속받고, 이는 CrudRepository, Repository를 상속받는다. 
- 해당 인터페이스에는 save( ), findOne( ), findAll( ), findById( )과 같이 직접 구현했던 기능들 뿐 아니라, 이 외에도 기본적인 CRUD를 수행하거나 단순 조회를 수행하는 기능과 count( ), delete( )와 같은 기능도 구현되어 있다. 
- 그래서 findByName( )만 작성하더라도 나머지 메서드는 자동 구현이 된다.

- findByName( ) 같이 공통으로 뽑을 수 없는 메서드들은 따로 인터페이스 안에 Optional<Member> findByName(String name);처럼 명시하면 스프링 데이터 JPA에서 자동으로  'select m from Member m where m.name=?'과 같은 JPQL 쿼리를 생성해 이를 사용할 수 있다.

스프링 데이터 JPA 제공 기능

  • 인터페이스를 통한 기본적인 CRUD
  • `findByName( )`, `findByAll( )`처럼 메서드 이름만으로 조회 기능 제공
  • 페이징 기능 자동 제공
  • 구현 클래스를 작성하지 않고, 인터페이스만을 작성해 개발이 끝날 수 있게 한다.

 

실무에서는 JPA와 스프링 데이터 JPA를 기본으로 사용하고, 복잡한 동적 쿼리는 Qurydsl이라는 라이브러리를 사용하면 된다. Querydsl을 사용하면 쿼리도 자바 코드로 안전하게 작성할 수 있고, 동적 쿼리도 편리하게 작성할 수 있다. 이 조합으로 해결하기 어려운 쿼리는 JPA가 제공하는 네이티브 쿼리를 사용하거나, 앞서 학습한 스프링 JdbcTemplate를 사용하면 된다.