[백엔드 강의] QueryDSL 설정 및 Spring Data JPA 테스트

이나형·2024년 8월 27일
0
post-thumbnail

이 포스팅은 인프런 강의 중 쥬쥬님의 '쥬쥬와 함께 하루만에 시작하는 백엔드 - 스프링, 도커, AWS' 에 올라온
코드 및 사진 이미지 모두 해당 강의를 참고하였습니다.

(인프런)쥬쥬와 함께 하루만에 시작하는 백엔드 - 스프링, 도커, AWS링크


QueryDSL

QueryDSL이란 정적 타입을 이용해서 SQL과 같은 쿼리를 생성할 수 있도록 해 주는 프레임워크다.
문자열로 작성하거나 XML 파일에 쿼리를 작성하는 대신, Querydsl이 제공하는 플루언트(Fluent) API를 이용해서 쿼리를 생성할 수 있다.



출처 : Querydsl 공식문서

QueryDSL 설정

지난 시간에는 JPA만 사용했는데, QueryDSL을 이용하여
원하는 값을 Database에서 읽어와서 사용할 수 있다.

@RequiredArgsConstructor //private final인 애들은 @AllArgsConstructor대신 사용해줄 수 있음.
@Configuration
public class QuerydlsConfig {
    private final EntityManager em;
    
    @Bean
    public JPAQueryFactory queryFactory(){
        return new JPAQueryFactory(em);
    }
}

이 코드를 통해 QueryDLS에 대한 설정을 완료할 수 있다.

@RequiredArgsConstructor과 @AllArgsConstructor차이


그런데 강사님께서는 이전까지는 롬복을 통해 생성자를 만들 때 @AllArgsConstructor를 사용하셨는데, 이번에는 @RequiredArgsConstructor 어노테이션을 사용하셨어서 둘이 어떤 차이가 있는지 찾아보았다.

@RequiredArgsConstructor과 @AllArgsConstructor차이


@RequiredArgsConstructor:

  • 적용대상 : 'final' 필드, '@NonNull'이 붙은 필드
    (다시 말하면, final이 아니거나 @NonNull이 없는 필드는 생성자에 포함되지 않는다.)
  • 'final' 필드만을 초기화하는 생성자를 간편하게 생성할 수 있다.
  • 'final' 필드는 한 번 초기화되면 더 이상 변경할 수 없기 때문에, 생성자를 통해 초기화 하는 것이 일반적이다.
  • @NonNull 필드에 대해 null 체크가 자동으로 추가되고, 해당 필드가 null이면 NullPointerException이 발생한다.


    @AllArgsConstructor:
  • 적용대상: 모든 필드('final'필드 상관 없이)
  • @NonNull 필드에 대해 null 체크가 포함된다.


    출처:Lombok 공식문서

Spring Data JPA를 활용한 데이터 처리 예제

Spring Data JPA 설정

@RequiredArgsConstructor
@Configuration
public class QuerydslConfig {
    private final EntityManager em;

    @Bean
    public JPAQueryFactory queryFactory(){
        return new JPAQueryFactory(em);
    }
}

이 코드는 'EntityManager'을 사용해 JPAQueryFactory 빈을 생성한다.

JPAQueryFactory는 Querydsl을 사용해 쿼리를 작성할 때 필요한 핵심 클래스이지만, 현재 코드에서는 Querydsl을 활용한 쿼리는 사용되지 않았다. 이 설정은 이후 Querydsl을 사용하기 위한 사전 준비라고 생각하면 된다.



Repository 생성

public interface TestRepository extends JpaRepository<TestEntity, Long>, TestRepositoryCustom {
    public List<TestEntity> findAllByName(String name);
}

이와 같이 전에 작성했던 TestRepository 인터페이스의 코드를 변경해준다.

findAllByName 메서드는 JPA의 메서드 쿼리 기능을 사용하여, 이름과 특정 값이 일치하는 모든 엔터티를 조회하는 기능이다.



Service 클래스 구현

전에 작성했던 TestService 클래스에서

public List<TestEntity> findAllByNameByJPA(String name){
        return testRepository.findAllByName(name);
    }

코드를 추가해준다.
findAllByNameByJPA 메서드는 JPA를 사용하여 이름이 특정 값인 모든 엔터티를 조회하는 기능을 한다.

Rest API 구현

코드가 잘 동작하는지 확인하기 위해 API 클래스를 작성해준다.

@RequiredArgsConstructor
@RestController
public class TestQueryApi {
    private final TestService testService;

    @GetMapping("/test/query/jpa")
    public List<TestEntity> queryJPA(){
        return testService.findAllByNameByJPA("jyujyu");
    }
}

이 클래스는 GET 요청을 처리하며, "/test/query/jpa" 엔드포인트로 요청이 들어오면 TestService의 findAllByNameByJPA 메서를 호출하여 이름이 "jyujyu"인 엔티티 목록을 반환하는 것이다.


그런 다음,

이제 Postman에서 다음과 같이 Send 버튼을 눌러 이름이 "jyujyu"인 데이터를 저장한다.


H2 데이터베이스에 'name'이 'jyujyu'이고 'age'가 20인 데이터가 들어왔음을 확인할 수 있다.

마지막으로, 방금 작성한 API의 기능을 확인하기 위해 Postman에서 API를 실행한다.


이 API를 통해, 이름이 "jyujyu"인 데이터를 성공적으로 조회할 수 있음을 확인할 수 있다.




데이터가 여러개 저장되어 있는 경우에도, 해당 데이터를 잘 조회하는지 확인하기 위해 name이 'backend'인 데이터도 데이터베이스에 저장하였다.



마찬가지로 이름이 'jyujyu'인 것만 잘 찾아내는 것을 확인할 수 있다.



profile
정도를 걷는 개발자

0개의 댓글