본문 바로가기
Java/ORM

JAVA ORM - Spring Data JPA(동적쿼리)

by 티코딩 2024. 8. 29.

ㅇ 동적쿼리란

실행 시점에 쿼리의 내용이 동적으로 생성되는 SQL쿼리. 입력이나 특정 조건에 따라 쿼리의 일부 또는 전체가 달라지는 쿼리.

String sql = "SELECT * FROM Users WHERE 1=1";

if (name != null) {
    sql += " AND name = '" + name + "'";
}

if (age != null) {
    sql += " AND age = " + age;
}

위의 코드에선 name이 null이 아니고, age가 null이 아니면,

최종 코드는

"SELECT * FROM Users WHERE 1=1 AND name = ' ㅇㅇㅇ ' AND age = ㅇㅇ'"
이렇게 작성된다.

 

ㅇ SpringDataJpa의 동적쿼리

Jpa에서 쿼리를 작성해야할땐 JPQL을 사용한다. 물론 네이티브쿼리를 사용할 수 도 있지만 단점들이 많다.

1. 플랫폼 종속성 :  데이터베이스별로 SQL문법이 다 다르기 때문에 한 데이터베이스에 종속되므로 추후에 데이터베이스를 교체하면 한줄한줄 교체하게 되어 이식성이 떨어진다.

2. 타입안전성 부족 : JPQL 또는 Criteria API를 사용하면 컴파일 시점에 쿼리의 타입을 체크할 수 있지만, 네이티브 쿼리는 문자열로 작성되어 컴파일 타임에 쿼리의 타입을 체크할 수 없다. 오직 런타임시점에만 오류를 발견할 수 있다.

이런 이유들 때문에 네이티브쿼리는 사용하면 안된다.

 

이제 Spring Data JPA에서 동적 쿼리를 어떻게 작성할까?

1. Spring Data JPA는 메서드 이름을 기반으로 쿼리를 자동으로 생성해준다.

List<User> findByUsernameAndStatus(String username, Status status);

이렇게 하다보면 이름이 너무 길어져서 좋지않다.

 

2.  @Query에너테이션을 사용해 JPQL쿼리

@Query("SELECT u FROM User u WHERE u.username = :username AND u.status = :status")
List<User> findByUsernameAndStatus(@Param("username") String username, @Param("status") Status status);

이런식으로 동적쿼리를 짤 수 있지만 완전히 동적인 쿼리를 작성하기엔 힘들다.

 

3. Example , ExampleMatcher를 사용한 동적 쿼리

User user = new User();
user.setUsername("john");

Example<User> example = Example.of(user, ExampleMatcher.matching().withIgnorePaths("status"));
List<User> users = userRepository.findAll(example);

Query by Example을 사용하면 엔티티의 샘플 객체를 기반으로 검색 조건을 생성할 순 있다.

 

 

ㅇ 결론

QueryDSL을 쓰자.