Spring/SpringDataJPA

공통 인터페이스 분석

느리지만 꾸준하게 2022. 4. 15. 21:28

MemberRepository Interface의 정체는 무엇인가?

package study.datajpa.repository;


import org.springframework.data.jpa.repository.JpaRepository;
import study.datajpa.entity.Member;

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

 

JpaRepository를 눌러서 열어보게 되면 여러가지 메서드가 나오게 된다.(spring-data-jpa library에 존재)

 

그리고 위에 패키지명을 보게되면 jpa.repository라고 되어있다.

package org.springframework.data.jpa.repository;

 

 

PagingAndSortingRepository은 눌러보면 package가 아래와 같이 나온다. 페이징하고 sorting하는 거는 관계형 데이터베이스든 noSQL이든 대부분 다 비슷하다. 그래서 공통 인터페이스가 제공이 된다.

commons에 PagingAndSortingRepository이 있다.(commons library에 존재)

package org.springframework.data.repository;

 

공통 인터페이스 구성 그림을 보면

스프링 데이터 부분은(common이라는 공통 부분이고) (=> 유사한 인터페이스로 편하게 개발할 수 있다.)

스프링 데이터 JPA는 JPA에 특화된 기능들만 제공을 한다.

메서드 종류는 아래와 같다.

  • save (S): entity 저장 / 존재하는 entity는 merge한다.
  • delete(T): entity 하나를 삭제. 내부에서 EntityManager.find()를 호출한다.
  • findById(ID): entity 하나를 조회 / 내부에서 EntityManager.find() 호출
  • getOne(ID): entity를 proxy로 조회한다. 내부에서 EntityManager.getReference() 호출 => getReference()는 진짜 entity를 찾지않고 가짜 proxy 객체를 가져오고 원할 때 꺼내어 db에 쿼리가 날라간다.
  • findAll: 모든 엔티티 조회 / 정렬 Sort이나 페이징 Pageble 조건을 파라미터로 제공

(JpaRepository는 대부분의 공통 메서드를 제공한다.)

 

MemberRepository Interface의 아래기능을 구현하려면

List<Member> findByUsername(String username);

// MemberRepository Interface

package study.datajpa.repository;


import org.springframework.data.jpa.repository.JpaRepository;
import study.datajpa.entity.Member;

import java.util.List;

public interface MemberRepository extends JpaRepository<Member, Long> {

    List<Member> findByUsername(String username);
}

MemberRepositryImpl을 만들어주고 인터페이스들 모두 다 Impl기능을 구현해주어야 한다. 즉 할 수가 없다.

// MemberRepositryImpl

package study.datajpa.repository;

import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.query.FluentQuery;
import study.datajpa.entity.Member;

import java.util.List;
import java.util.Optional;
import java.util.function.Function;

public class MemberRepositoryImpl implements MemberRepository{
    @Override
    public List<Member> findByUsername(String username) {
        return null;
    }

    @Override
    public List<Member> findAll() {
        return null;
    }

    @Override
    public List<Member> findAll(Sort sort) {
        return null;
    }

    @Override
    public Page<Member> findAll(Pageable pageable) {
        return null;
    }

    @Override
    public List<Member> findAllById(Iterable<Long> longs) {
        return null;
    }

    @Override
    public long count() {
        return 0;
    }

    @Override
    public void deleteById(Long aLong) {

    }

    @Override
    public void delete(Member entity) {

    }

    @Override
    public void deleteAllById(Iterable<? extends Long> longs) {

    }

    @Override
    public void deleteAll(Iterable<? extends Member> entities) {

    }

    @Override
    public void deleteAll() {

    }

    @Override
    public <S extends Member> S save(S entity) {
        return null;
    }

    @Override
    public <S extends Member> List<S> saveAll(Iterable<S> entities) {
        return null;
    }

    @Override
    public Optional<Member> findById(Long aLong) {
        return Optional.empty();
    }

    @Override
    public boolean existsById(Long aLong) {
        return false;
    }

    @Override
    public void flush() {

    }

    @Override
    public <S extends Member> S saveAndFlush(S entity) {
        return null;
    }

    @Override
    public <S extends Member> List<S> saveAllAndFlush(Iterable<S> entities) {
        return null;
    }

    @Override
    public void deleteAllInBatch(Iterable<Member> entities) {

    }

    @Override
    public void deleteAllByIdInBatch(Iterable<Long> longs) {

    }

    @Override
    public void deleteAllInBatch() {

    }

    @Override
    public Member getOne(Long aLong) {
        return null;
    }

    @Override
    public Member getById(Long aLong) {
        return null;
    }

    @Override
    public <S extends Member> Optional<S> findOne(Example<S> example) {
        return Optional.empty();
    }

    @Override
    public <S extends Member> List<S> findAll(Example<S> example) {
        return null;
    }

    @Override
    public <S extends Member> List<S> findAll(Example<S> example, Sort sort) {
        return null;
    }

    @Override
    public <S extends Member> Page<S> findAll(Example<S> example, Pageable pageable) {
        return null;
    }

    @Override
    public <S extends Member> long count(Example<S> example) {
        return 0;
    }

    @Override
    public <S extends Member> boolean exists(Example<S> example) {
        return false;
    }

    @Override
    public <S extends Member, R> R findBy(Example<S> example, Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction) {
        return null;
    }
}

 

List<Member> findByUsername(String username);  이 기능만 구현하는 커스텀 기능에 대해선은 나중에 자세히 다뤄보자.

 

Query Method 기능을 이용하면 아래 기능을 구현하지 않아도 스프링 데이터 JPA는 동작을 하게 된다.

List<Member> findByUsername(String username);

 

 

 

 

 

 

 

 

 

 

 

 

 

 

<출처 김영한: 실전! 스프링 데이터 JPA >

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%8D%B0%EC%9D%B4%ED%84%B0-JPA-%EC%8B%A4%EC%A0%84/dashboard

 

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

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

www.inflearn.com