Back-End/Spring (SpartaCC)

[Spring] JPA - SpringData, JpaRepository, QueryDSL

남건욱 2023. 7. 27. 19:09
반응형
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 를위해 도메인 중심으로 모듈이 분리될 수 있는 구조로 프로젝트들이 발전해오고 있다.

반응형
프로필사진

남건욱's 공부기록