JPA/스프링 데이터 JPA

@Query - 쿼리 정의하기

chanhee01 2023. 8. 11. 21:20
public interface MemberRepository extends JpaRepository<Member, Long> {

    @Query("select m from Member m where m.username = :username and m.age = :age")
    List<Member> findUser(@Param("username") String username, @Param("age") int age);
}

Repository에 @Query 어노테이션으로 쿼리를 정의해서 사용할 수 있다. 이러한 방식의 장점은 첫 번째로 findByUsernameAndAgeGreaterThan() 같이 메서드 이름으로 자동으로 쿼리를 날려주는 방식은 2가지 조건만으로도 메서드명이 길어지는데 위의 방식은 그렇지 않고, 내가 보내고싶은 쿼리를 명확하게 알 수 있다는 장점이 있다.

 

이 방식의 장점은 쿼리 절에서 오타가 난다고할 지라도 애플리케이션 실행 시점에 오류를 잡아준다는 것이다.

@Query("select m from Member m where m.usernameaaaaa = :username and m.age = :age")

usernameaaaaa라는 이상한 문자열이 있으면 문법 오류로 컴파일 시점에 잡아주기 때문에 오타로 인한 실수가 줄어들게 된다.

 

 

심플한 방식은 메서드 이름으로 자동으로 쿼리를 만들어주는 방식을 사용하고 그렇지 않은 경우에는 이렇게 @Query 어노테이션으로 만들어주면 된다.

 

 

 

 

@Query로 값, DTO 조회하기

 

- 값 조회

@Query("select m.username from Member m")
List<String> findUsernameList();

m.username을 가져오는데 m.username은 String 타입이기 때문에 그냥 이렇게 쉽게 가져오면 된다.

 

 

- DTO 조회

@Data
public class MemberDto {
    
    private Long id;
    private String username;
    private String teamName;
    
    public MemberDto(Long id, String username, String teamName) {
        this.id = id;
        this.username = username;
        this.teamName = teamName;
    }
}

받아올 값들을 별도의 Dto를 만들어서 생성자를 만들어준다.

 

@Query("select new study.datajpa.dto.MemberDto(m.id, m.username, t.name) from Member m join m.team t")
List<MemberDto> findMemberDto();

@Query에 select 할때 new 뒤에 패키지명을 전부 다 적어줘야 한다. 이렇게 하면 컨트롤러에서 findMemberDto()를 호출하면 member의 id, username, 팀명을 Dto로 받아와서 반환해준다.

 

 

 

 

 

컬렉션 파라미터 바인딩

쿼리안에 :username 이렇게 해서 넣는걸 파라미터 바인딩이라고 하는데 컬렉션도 파라미터 바인딩을 사용할 수 있다.

@Query("select m from Member m where m.username in :names")
List<Member> findByNames(@Param("names") Collection<String> names);

in 문법을 사용해서 Collection을 넘겨주면 컬렉션 파라미터 바인딩이 된다.