SpringData 기능 목록
- 강력한 리포지토리 및 사용자 지정 객체 매핑 추상화
- 리포지토리 메서드 이름에서 동적 쿼리 파생
- 기본 속성을 제공하는 구현 도메인 기본 클래스
- 명료한 추적기능 지원(생성일시, 마지막 변경일시, 생성자, 마지막 변경자)
- 사용자 지정 리포지토리 코드 통합 가능성
- JavaConfig 및 사용자 지정 XML 네임스페이스를 통한 간편한 Spring 통합
- Spring MVC 컨트롤러와의 고급 통합
- 교차 스토어 지속성에 대한 실험적 지원
SpringData Jpa와 JpaRepository의 원리
- Repository는 MarkerInterface로 특별한 기능은 없다.
- Repository ~ JpaRepository 까지는 @NotRepositoryBean 이 붙어있는 인터페이스이다.
- JpaRepository <Entity, ID> 붙이면 알맞은 프로그래밍된 SimpleJpaReository 구현체 빈이 등록된다.
- 등록되는원리 : @SpringBootApplication을 통해 자동으로 붙여지는 @EnableJpaRepositories의
JpaRepositoriesRegistrar를 통해서 등록된다.
- JpaRepositoriesRegistrar는 ImportBeanDefinitionRegistrar의 구현체이다.
- ImportBeanDefinitionRegistrar는 프로그래밍을 통해 빈을 주입해 준다.
기존 Repository와 새로운 JpaRepository
기존 Repository
- @Repository을 클래스에 붙인다.
- 앞서배운 RawJPA의 Repository 기능만 가진 구현체가 생성된다. (DB별 예외처리 등)
새로운 JpaRepository
- JpaRepository <Entity, ID> 인터페이스를 인터페이스에 extends 붙인다.
- @NotRepositoryBean 된 상위 인터페이스들의 기능을 포함한 구현체가 프로그래밍된다. (@NotRepositoryBean = 빈생성 막음)
- SpringDataJpa에 의해 엔티티의 CRUD, 페이징, 정렬 기능 메서드들을 가진 빈이 등록된다. (상위 인터페이스들의 기능)
JpaRepository 팁
JpaRepository에서 사용할 메서드 제한하기
- JpaRepository는 기본적으로 모든 기능을 제공하기 때문에 리스크가 있을 수 있다.
- 원하는 기능 메서드만 구현하도록 제한할 수 있다. (@RepositoryDefinition / @NoRepositoryBean) 전자가 가장 많이 쓰인다.
페이징 처리 프로세스
- PageRequest를 사용하여 Pageable에 페이징 정보를 담아 객체화한다.
- Pageable을 JpaRepository가 상속된 인터페이스의 메서드에 T(Entity)와 함께 파라미터로 전달한다.
- 위의 메서드의 return으로 Page <T>가 응답된다.
- 응답된 Page <T>에 담겨진 Page 정보를 바탕으로 로직을 처리하면 된다.
페이지 반환 타입
Page <T> 타입
- 게시판 형태의 페이징에서 사용된다.
- 전체 요소 개수도 함께 조회한다. (totalElements)
- 응답은 위와 동일하다.
Slice <T> 타입
- 더 보기 형태의 페이징에서 사용된다.
- 전체 요소 개수 대신 offset 필드로 조회할 수 있다.
- 따라서 count 쿼리가 발생되지 않고 limit+1 조회를 한다. (offset 은 성능이 안 좋아서 현업에서 사용하지 않는다고 한다.)
List <T> 타입
- 전체 목록보기 형태의 페이징에서 사용된다.
- 기본 타입으로 count 조회가 발생하지 않는다.
List <t>가 필요하면 응답을 Page <t>로 받지 말고 List <T>로 받는 것이 좋다.
- 전체 count 쿼리가 추가로 발생하는 Page <T> 보다는 List <T>가 대용량 처리할 때 더 안정적이고 빠르다.
SpringData 쿼리
기능
- SpringData Common의 CRUDRepository + PagingAndSortingRepository이 쿼리기능을 제공한다.
사용 방법
- 리턴타입 {접두어}{도입부} By {프로퍼티 표현식}{조건식}[And|Or){프로퍼티 표현식}(조건식)](OrderBy {프로퍼티} Asc|Desc)(매개변수..)
QueryDSL
기능
- QueryDSL의 Predicate 인터페이스로 조건문을 여러 개를 구성하여 따로 관리할 수 있다.
- findOne(Predicate), findAll(Predicate) 주로 이 2개 메서드가 사용된다.
- findOne = Optional <T> 리턴
- findAll = List <T> | Page <T> | Iterable <T> | Slice <T> 리턴
Type Safe 기능
- 조건문 구성시에 사용되는 객체, 필드 조건이 실제 타입과 일치한 지 체크해 준다.
장점
- 문자가 아닌 코드로 쿼리를 작성함으로써, 컴파일 시점에 문법 오류를 쉽게 확인할 수 있다.
- 자동 완성 등 IDE의 도움을 받을 수 있다.
- 동적인 쿼리 작성이 편리하다.
- 쿼리 작성 시 제약 조건 등을 메서드 추출을 통해 재사용할 수 있다.
원리
- QueryDSL 의존성을 추가하면 SpringData에 의해 QueryDslPredicateExecutor 인터페이스가 추가된다.
- QueryDslPredicateExecutor는 Repository가 QueryDsl을 실행할 수 있는 인터페이스를 제공하는 역할을 한다.
사용방법
- Spring 2.X 버전까지는 QueryDSL 빌드 Task를 따로 설정해줘야 했다.
- Spring 3.X 버전부터는 의존성만 추가하면 빌드에 자동으로 포함돼서 실행된다.
Auditing
- 생성일시, 생성자, 수정일시, 수정자는 결국 엔티티의 영속성이 변경될 때 저장한다.
- 엔티티의 영속성이 변경되는 생성 > 수정 > 삭제 이 흐름을 엔티티 라이프 사이클 이벤트라고 한다.
- Auditing 도 이러한 엔티티의 라이프 사이클 이벤트를 통해 구현하고 있다.
- 우린 엔티티 라이프 사이클을 직접 관리하여 구현할 수 있다.
- 객체가 생성되면 자동으로 실행하도록 메서드에 붙이는 @PostConstruct의 원리와 같다.
엔티티 저장이벤트
전 - @PrePersist : EntityManager 가 엔티티를 영속성상태로 만들기 직전에 메서드 수행
후 - @PostPersist : EntityManager 가 엔티티를 영속성상태로 만든 직후에 메소드 수행
엔티티 수정 이벤트
전 - @PreUpdate : EntityManager 가 엔티티를 갱신상태로 만들기 직전에 메소드 수행
후 - @PostUpdate : EntityManager 가 엔티티를 갱신상태로 만든 직후에 메소드 수행
엔티티 삭제 이벤트
전 - @PerRemove : EntityManager 가 엔티티를 삭제상태로 만들기 직전에 메소드 수행
후 - @PostRemove : : EntityManager 가 엔티티를 삭제상태로 만든 직후에 메소드 수행
Jpa로 쿼리를 짜기 어렵지만 사용하는 이유
- JPA로 많이 넘어간 까닭은, 데이터모델이 단순해진 탓
- 대신 데이터 흐름이 매우 정교 해졌다.
- DDD(도메인 주도 개발)이 중심이 되어가고 있기 때문에.
- MSA 를위해 도메인 중심으로 모듈이 분리될 수 있는 구조로 프로젝트들이 발전해오고 있다.
'Back-End > Spring (SpartaCC)' 카테고리의 다른 글
[Spring] 자주 사용하는 Annotation (개인적) (0) | 2023.07.27 |
---|---|
[Spring] JPA - JPQL, QueryDSL, N+1 문제 (0) | 2023.07.27 |
[Spring] JPA - ORM의 배경, Raw JPA 기능 (0) | 2023.07.27 |
[Spring] 스파르타코딩클럽 Spring공부(6) - OAuth, 단위테스트, 통합테스트, 예외처리관리 (1) | 2023.07.10 |
[Spring] 스파르타코딩클럽 Spring공부(5) - Validation, Entity 관계 (0) | 2023.06.23 |
남건욱's 공부기록