SpringBoot 조건문 처리 방법에 대해 알아보자

청포도봉봉이·2023년 10월 30일
1

Spring

목록 보기
27/35
post-thumbnail

💎 개요

개인 프로젝트를 하던 중 검색에 따라서 list의 출력 값이 나오게 하고 싶었다. 그래서 JPA를 이용한 조건절 구현에 대해서 찾아보았고 이를 정리하고 싶었다.


💎 방법


JPQL을 이용하는 방법

EntityManager를 통해 JPQL을 실행하려면, createQuery 메서드에 JPQL 쿼리 문자열을 전달하면 된다. 이는 Query 인스턴스를 반환하며, 이 인스턴스의 getResultList 또는 getSingleResult 메서드를 호출하여 쿼리 결과를 얻을 수 있다.

String jpql = "SELECT p FROM Post p WHERE p.title = :title AND p.content = :content";
Query query = entityManager.createQuery(jpql);
query.setParameter("title", "Hello");
query.setParameter("content", "World");
List<Post> result = query.getResultList();

  • 장점

    • 객체 지향적인 쿼리: JPQL은 SQL과 비슷하지만, 객체 지향적인 쿼리를 작성할 수 있다. 따라서 개발자는 데이터베이스 테이블이 아닌 자바 클래스와 그 관계에 집중할 수 있다.

    • 데이터베이스 중립적: JPQL은 특정 데이터베이스에 종속되지 않는다. 즉, 같은 JPQL 쿼리를 다양한 데이터베이스에서 사용할 수 있다.

    • 타입 안전성: JPQL은 컴파일 시점에 문법 오류를 찾아낼 수 있다. 이는 실행 시점에 발생할 수 있는 오류를 미리 방지하는 데 도움이 된다.

  • 단점

    • 복잡한 쿼리 작성 어려움: JPQL은 SQL보다 간단한 쿼리를 작성하는 데 유리하지만, 조인, 서브 쿼리 등 복잡한 쿼리를 작성하는 데는 한계가 있다.

    • 성능 최적화 어려움: JPQL은 SQL을 추상화한 것이므로, 때때로 SQL에 직접 접근하는 것보다 성능 최적화가 어려울 수 있다.

    • 동적 쿼리 작성 어려움: 문자열로 쿼리를 작성하는 방식이므로, 동적으로 쿼리를 생성하거나 수정하는 것이 복잡하고 오류 발생 가능성이 높다.




Criteria API를 이용하는 방법

JPA의 Criteria API를 사용하여 조건문을 처리할 수 있다. Post라는 Entity를 가지고 예시를 들어보겠다. 가령, title이 특정 문자열을 포함하는 Post를 찾고 싶은 경우, 아래와 같이 작성할 수 있다.

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Post> cq = cb.createQuery(Post.class);
Root<Post> post = cq.from(Post.class);
Predicate titlePredicate = cb.like(post.get("title"), "%yourTitle%");
cq.where(titlePredicate);
TypedQuery<Post> query = entityManager.createQuery(cq);
List<Post> result = query.getResultList();

  • 장점: JPA의 기본 기능을 사용하기 때문에 추가적인 라이브러리 없이 사용할 수 있다. 또한, SQL에 익숙한 사용자는 비교적 쉽게 사용할 수 있다.

  • 단점: 코드가 복잡하고 가독성이 떨어진다. 또한, Criteria API는 JPA 2.0부터 지원되므로, 이전 버전의 JPA를 사용하는 경우 사용할 수 없다.




Specification을 이용하는 방법

Specification은 Spring Data JPA에서 제공하는 인터페이스로, 동적으로 쿼리를 생성하기 위한 명세를 정의하는 데 사용된다.

Spring Data JPA에서는 Specification을 사용하여 동적 쿼리를 작성할 수 있다. Specification은 Predicate를 생성하는 로직을 캡슐화한 것으로, JpaSpecificationExecutor 인터페이스를 상속받은 Repository에서 사용할 수 있다.

public class PostSpecification {

    public static Specification<Post> titleContains(String title) {
        return (root, query, criteriaBuilder) -> criteriaBuilder.like(root.get("title"), "%" + title + "%");
    }

}

// Repository에서 사용하는 예시
List<Post> result = postRepository.findAll(PostSpecification.titleContains("yourTitle"));

  • 장점: 코드가 간결하고 가독성이 좋다. 또한, Specification을 재사용할 수 있어 유지보수성이 좋다.

  • 단점: Spring Data JPA에 의존성이 있다. 따라서, Spring Data JPA를 사용하지 않는 환경에서는 사용할 수 없다.




QueryDSL을 이용하는 방법

QueryDSL은 동적으로 SQL, JPQL, JDOQL, 이외에도 다양한 쿼리를 생성하고 실행할 수 있는 프레임워크이다. QueryDSL은 타입 세이프한 쿼리를 작성할 수 있도록 도와준다. 즉, 쿼리를 작성하는 코드 자체가 컴파일러에 의해 타입 체크가 되므로, 쿼리에 문제가 있으면 컴파일 시점에 바로 알 수 있다.

JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
QPost post = QPost.post;

List<Post> result = queryFactory.selectFrom(post)
    .where(post.title.contains("yourTitle"))
    .fetch();

  • 장점: 코드가 간결하고 가독성이 좋다. 또한, 컴파일 시점에 쿼리 오류를 잡을 수 있어 안정성이 좋다.

  • 단점: 추가적인 라이브러리를 필요로 하다. 따라서 프로젝트 설정이 복잡하며, 학습 비용이 크다.




@Query를 이용하는 방법

@Query 애노테이션을 이용하여 JPQL을 작성할 수 있다.

public interface PostRepository extends JpaRepository<Post, Long> {
   @Query("SELECT p FROM Post p WHERE p.title = :title")
   List<Post> findByTitle(@Param("title") String title);
}

:title은 파라미터 바인딩을 나타낸다. @Param 애노테이션을 이용하여 메서드 파라미터와 바인딩할 수 있다.

  • 장점

    • 쿼리의 가독성 향상: @Query를 사용하면 메서드 위에 직접 쿼리를 작성할 수 있으므로, 메서드가 수행하는 쿼리를 쉽게 파악할 수 있다.

    • 복잡한 쿼리 작성 가능: @Query를 이용하면 JPQL 뿐만 아니라 네이티브 SQL도 작성할 수 있다. 따라서 복잡한 쿼리나 데이터베이스에 특화된 쿼리를 작성하는데 유용하다.

    • 동적 쿼리 작성 용이: @Query를 사용하면 쿼리에 동적으로 파라미터를 바인딩할 수 있다. 이는 동적 쿼리를 작성하는데 유용하다.

  • 단점

    • 쿼리 오류 발견이 늦음: @Query에 작성한 쿼리의 오류는 애플리케이션을 실행한 후에야 발견할 수 있다. 이는 개발 과정에서 시간을 낭비할 수 있다.

    • 코드 중복 가능성: 비슷한 쿼리가 여러 메서드에서 사용될 경우, @Query를 이용하면 같은 쿼리를 여러 번 작성해야 할 수 있다. 이는 코드의 중복을 초래할 수 있다.

    • QueryDSL 등 다른 쿼리 작성 방식과 비교했을 때 타입 안정성이 떨어짐: @Query는 문자열로 쿼리를 작성하므로, 컴파일 시점에 쿼리 오류를 잡아내지 못하고, 실행 시점에 오류가 발견된다. 이에 반해 QueryDSL은 타입 세이프한 쿼리를 작성할 수 있어 안정성이 더 높다.

profile
서버 백엔드 개발자

0개의 댓글