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 >
실전! 스프링 데이터 JPA - 인프런 | 강의
스프링 데이터 JPA는 기존의 한계를 넘어 마치 마법처럼 리포지토리에 구현 클래스 없이 인터페이스만으로 개발을 완료할 수 있습니다. 그리고 반복 개발해온 기본 CRUD 기능도 모두 제공합니다.
www.inflearn.com
'Spring > SpringDataJPA' 카테고리의 다른 글
JPA NamedQuery (0) | 2022.04.17 |
---|---|
메소드 이름으로 쿼리 생성 (0) | 2022.04.15 |
공통 인터페이스 설정 & 적용 (0) | 2022.04.15 |
공통 인터페이스 기반 - 순수 JPA 기반 레포지토리 만들기 (0) | 2022.04.15 |
예제 도메인 모델 - 예제 도메인 모델과 동작확인 (0) | 2022.04.15 |