Today I Learned
(24.07.03)[12주차] QueryDSL사용을 위한 Repository 분리
QueryDSL로 JPA에서 쿼리문을 구현하려고 했지만, 기존에 JpaRepository 를 상속받는 Repository를 사용하고 있었기에 내부에 QueryDSL 쿼리역시 구현을 할 수 없었다.
그렇다고 Service단에서 그 쿼리를 구현하는 것은 계층을 분리하고자 하는 의의와 벗어나게 되는데,
그렇다면 어떻게 QueryDSL을 사용할 수 있을지에 대한 구조 정리
QueryDSL을 사용하기 위한 Repository 구성
- JpaRepository만 상속 받는 형태의 Repository로 Service 계층에서 findBy save delete 등의 쿼리 메서드를 사용할 수 있었지만, QueryDSL을 사용하기 위해서는 이 상속받고 있는 Repository를 사용하는 것이 아닌 위의 그래프처럼 Custom Repository를 만들어 줘야한다.
- 해당 구성은 실제로 사용되는 구조
- interface의 특징을 잘 알고 있으면 사용할 수 있듯이 정상적으로 사용되는 부분인 만큼 기억을 할 수 있도록해야한다.
Custom Repository 생성
public interface LikeJpaRepository {
Optional<Like> findByApartIdAndUser(Long apartId, User user);
...
- 위의 코드를 예시로 좋아요 기능을 위한 좋아요 엔터티의 LikeRepository가 있을 경우에 QueryDSL로 구현을 해야하는 메서드들을 모은 interface인 Custom Repository를 생성
- ○○○RepositoryCustom 이라고 통상적으로 사용하지만, 여러 Repository가 있는 상황에서 좀더 Repository가 명확하게 어떤 Repository인지 확실히 하기 위해서 ○○○JpaRepository 로 임의로 정했음
구현 RepositoryImpl 생성
public class LikeRepositoryImpl implements LikeJpaRepository {
...
private final JPAQueryFactory jpaQueryFactory;
...
@Override
public Optional<Like> findByApartIdAndUser(Long apartId, User user) {
Like like = jpaQueryFactory.selectFrom(qLike)
.where(qLike.apart.id.eq(apartId).and(qLike.user.userName.eq(user.getUserName())))
.fetchOne();
return Optional.ofNullable(like);
}
...
- ○○○JpaRepository 에 Service에서 사용할 메서드를 추가가 되었다면, interface이므로 이를 구현시켜줄 Impl 클래스를 생성해서 구현
- implements ○○○JpaRepository 를 하고 @Override를 통해 QueryDSL 을 사용해서 해당 메서드의 기능을 구현
- interface의 반드시 구현되어야하는 특징을 해결하기 위한 클래스라고 생각하면 편함
기존 Repository에 구현
public interface LikeRepository extends JpaRepository<Like, Long>, LikeJpaRepository{
...
- interface끼리는 서로 다중 상속이 가능하므로 extends를 사용해서 쓸 수 있음
- 따라서, Service에서 LikeRepository를 주입받아 likeRepository.findByApartIdAndUser 처럼 사용할 수 있고, 이는 LikeRepositoryImpl에서 QueryDSL로 구현된 메서드를 사용할 수 있는 것
계층 분리의 장점 정리
테스트 용이성
- Service단에서 QueryDSL을 직접 구현을 해버리면 해당 쿼리를 검증하는데 Serivce의 단위테스트에서 진행을 해야될지 또는 통합으로 Slice Test로 진행을 해야할지 구분하기 매우 애매해진다.
- QueryDSL 자체는 DB에 직접 접속해서 작업을 처리하는 단게이므로 Repository 계층에 맞기 때문에
- 따라서, 테스트 작성에서도 단순화 시키면서 복잡한 쿼리를 따로 검증할 수 있는 용이성이 있음
유지보수성
- QueryDSL도 Repository에 사용하기 위해 분리함으로써 Service는 Repository단의 오류나 기능작동 즉, QueryDSL에서의 오류를 담당하지 않기 때문에 Repository단에서만 해당 이슈를 해결할 수 있음
재사용성
- QueryDSL도 query단위로 재사용할 수 있지만, 그 통째로 구현되는 QueryDSL 로 구성된 메서드도 Repository주입을 통해서 여러 서비스 단에서 공통적으로 사용할 수도 있음
계층을 분리를 하는 것을 알고 있었지만,
Repository를 여러개를 만들경우에는 interface를 사용해서 여러개를 상속 extends 할 수 있는 방향으로 진행을 해도 크게 문제가 되는 포인트가 없다는 것을 이번 학습을 통해서 알았기에
필요가 있다면, 위 코드드들을 참고해서 바로 쓸 수 있도록 해야할 것.
'Today I Learned' 카테고리의 다른 글
(24.07.09)[13주차] @DataJpaTest 슬라이스 테스트에서의 빈 등록 (0) | 2024.07.09 |
---|---|
(24.07.04)[12주차] Redis 강의 학습 (0) | 2024.07.04 |
(24.07.02)[12주차] QueryDSL의 Wildcard 와 Count (0) | 2024.07.02 |
(24.06.28)[11주차] QueryDSL과 SQL의 비교와 정리 (0) | 2024.06.28 |
(24.06.27)[11주차] JPA 심화 강의 02 (마무리) (0) | 2024.06.27 |