스프링 입문 - 스프링 데이터 JPA
우리가 SpringBoot와 JPA만 사용을 해도 개발 생산성이 정말 많이 증가한다.
개발 해야할 코드도 엄청나게 줄어든다.
그런데, 여기에다가 SpringDataJPA를 사용하면,
우리가 "이것까진 안되지 않을까?" 라는 이러한 한계를 넘어서,
정말 마법처럼, 인터페이스만으로 개발을 완료할 수 있다.(물론 디테일 하게 들어가면 조금 다를수도..)
그리고, 반복적으로 개발해온 기본 CRUD 기능도 스프링 데이터 JPA가 모두 제공해준다.
스프링 부트와 JPA라는 기반 위에, 스프링 데이터 JPA라는 환상적인 프레임워크를 더하면,
지금까지 조금이라도 단순하고 반복이라 생각했던 개발 코드들이 확연하게 줄어든다.
따라서, 엔지니어/개발자는 핵심 비즈니스 로직을 개발하는데, 집중할 수 있다.
실무에서 관계형 데이터베이스를 사용한다면, 스프링 데이터 JPA는 이제는 선택이 아니라 필수이다.
※ 주의 : 스프링 데이터 JPA는 JPA를 편리하게 사용하도록 도와주는 기술이다. 따라서 JPA를 먼저 학습하고, 스프링 데이터 JPA를 학습하자.
스프링 데이터 JPA
설정은 JPA 설정을 그대로 사용한다.
repository폴더에 SpringDataJpaMemberRepository 라는 이름으로 인터페이스를 생성했다.
그리고, SpringDataJpaMemberRepository 인터페이스에서 JpaRepository 라는 인터페이스를 상속받도록 했다.
참고로, 인터페이스가 인터페이스를 받을 때는 implements가 아니라 extends 이다.
그리고, 지네릭타입으로 첫번째는 Member, 두번째는 엔티티에서 식별자 PrimaryKey인 Id의 타입인 Long 이다.
그리고, 인터페이스는 다중상속이 가능하다.
그래서 MemberRepository 인터페이스도 상속시켜주었다.
그리고,
@Override
Optional<Member> findByName(String name);
이렇게 적어주었다.
이렇게만 해주면 구현을 다한것이다.
!!!!?
이게 어떻게 가능한지 알아보도록 하겠다.
우선,
SpringDataJpaMemberRepository를 보면, 인터페이스만 있다.
이렇게, SpringDataJpaMemberRepository가 JpaRepository를 상속받고 있으면,
SpringDataJpa가 구현체를 자동으로 만들어준다.
내가 스프링빈에 등록하는게 아니라,
스프링데이터jpa가 자동으로 구현체를 만들어서 스프링빈에 등록을 해준다.
우리는 그것을 그냥 가져다가 쓰면 된다.
어떻게 가져다 쓰냐면,
이렇게 memberRepository를 그냥 인젝션 받으면 된다.
(이렇게 생성자가 하나인 경우에는 @Autowired 생략하는 것도 가능하다.)
그러면, 스프링데이터Jpa가 구현체로 만들어 놓은 것이 등록이 된다.
그리고 memberService에다가 의존관계 세팅을 해주자.
방금 인젝션 받은 memberRepository를 MemberService에 의존관계 세팅을 해주었다.
이런 경우에는 스프링 컨테이너에서 MemberRepository를 찾는다.
그런데, MemberRepository는 지금 내가 등록한게 없다.
등록되어있는 것은 1개가 있는데,
SpringDataJpaMemberRepository가 스프링 컨테이너에 등록되어 있다.
SpringDataJpa가 제공하는 JpaRepository를 상속받은 인터페이스만 만들어 놓으면,
SpringDataJpa가 해당 인터페이스에 대한 구현체를 자동으로 생성해서 스프링빈에 자동으로 등록해준다.
그래서 우리는, 이러한 방식으로 인젝션을 받을 수 있는 것이다.
이제 한번 돌려보자.
먼저 스프링통합테스트로 회원가입만 살짝 돌려보자.
테스트에 통과했다.
로그를 살펴보면, Hibernate 구현체가 사용된 것을 볼 수 있다.
즉, SpringDataJpa가 JPA기술을 가져다 쓰는 것을 알 수 있다.
이번에는 스프링 통합테스트로 전체 테스트를 돌려보자.
테스트에 잘 통과한 것을 볼 수 있다.
스프링데이터Jpa가 SpirngDataJpaMemberRepository 인터페이스를 보고,
프록시라는 기술을가지고 객체를 생성을 해서 스프링빈에 자동으로 등록해준다.
그러면, 우리는 그것을 인젝션해서 사용한 것이다.
자, 그러면, 기본적인 save(),findOne()같은 메서드는 다 어디에 있는 걸까?
사실, 여기에 다 있다.
스프링 데이터 JPA가 기본적으로 JpaRepository에서 findAll(), save() 등을 제공한다.
그리고, CrudRepository에서 기본적인 save() 등을 제공한다.
이렇게 우리가 머릿속으로 상상할 수 있는것들은 공통화해서 거의다 제공을 해준다.
JpaRepository에 들어가보면,
이런식으로 기본메서드들이 다 제공이 된다.
PagingAndSortingRepository까지 들어가보면,
페이징처리, 조회까지 해준다.
그리고 CrudRepository 까지 들어가보면,
우리가 만들었던 save, findById 등이 기본적으로 제공된다.
이러한 기본적인 CRUD와 단순조회들이 다 제공된다.
그래서, 우리가 생각할 수 있는 기본적인 것들은 공통화해서 거의다 만들어져 있다.
그래서 그것을 그냥 가져다가 쓰면 되는 것이다.
그런데, 아무리 공통화를 해도, 못만드는게 있다.
예를 들어서
@Entity Member를 보자.
내가 name으로 찾고 싶은지, 이메일이름으로 찾고싶은지,
이러한 것들은 비즈니스가 다 다르기 때문에 공통화 하는게 불가능하다.
그래서 공통 클래스로 제공 할 수가 없다.
내가 만든 프로젝트인 경우에야, Member가 name으로 찾을 수 있지만,
다른 회사에서는 username이라고 할 수도 있고, 다른 객체들이 굉장히 많이 있으니깐 말이다.
그리고, 주문할때도, 주문서 번호로 조회할 지, 고객이 주문한 상품이름으로 조회할지,
이런것들은 인터페이스를 통한 메서드로 공통화 할 수 있는 것이 아니다.
그래서 SrpingDataJpaMemberRepository에다가
findByName을 만들어주면, 어떤 일이 벌어지냐면,
이게 규칙이 있는데, findByName 에서는 name으로 찾는다.
JPQL select m from Member m where m.name = ?
자동으로 이런식으로 JPQL이 짜지고, 이게 SQL로 번역이 되서 실행된다.
이것 외에도 findByNameAndId(String name, Long id); 이런식으로 And , Or 등등 여러가지가 있다.
어쨋든, 단순한 것들은 이렇게 인터페이스 이름만으로도 개발이 끝난다.
스프링 데이터 JPA 제공 기능
- 인터페이스를 통한 기본적인 CRUD
- findByName((), findByEmail()처럼 메서드 이름 만으로 조회 기능 제공
- 페이징 기능 자동 제공
※ 참고
실무에서는 JPA와 스프링 데이터 JPA를 기본으로 사용하고, 복잡한 동적 쿼리는 Querydsl이라는 라이브러리를 사용하면 된다. Querydsl을 사용하면 쿼리도 자바 코드로 안전하게 작성할 수 있고, 동적 쿼리도 편리하게 작성할 수 있다.
이 조합으로 해결하기 어려운 쿼리는 JPA가 제공하는 네이티브 쿼리를 사용하거나 앞서 학습한 스프링 JdbcTemplate를 사용하면 된다.
'Spring' 카테고리의 다른 글
스프링 입문 - AOP 적용 (0) | 2022.05.23 |
---|---|
스프링 입문 - AOP가 필요한 상황 (0) | 2022.05.23 |
스프링 입문 - JPA (0) | 2022.05.22 |
스프링 입문 - 스프링 JdbcTemplate (0) | 2022.05.22 |
스프링 입문 - 스프링 통합 테스트 (0) | 2022.05.22 |
댓글
이 글 공유하기
다른 글
-
스프링 입문 - AOP 적용
스프링 입문 - AOP 적용
2022.05.23 -
스프링 입문 - AOP가 필요한 상황
스프링 입문 - AOP가 필요한 상황
2022.05.23 -
스프링 입문 - JPA
스프링 입문 - JPA
2022.05.22 -
스프링 입문 - 스프링 JdbcTemplate
스프링 입문 - 스프링 JdbcTemplate
2022.05.22