본문 바로가기

Spring boot/스프링 데이터 JPA

[spring boot] @Query, 메서드 이름으로 생성, NamedQuery

스프링 데이터 JPA가 제공하는 기능 (사용 순위)

  1. @Query 어노테이션을 사용해서 repository interface에 쿼리 직접 정의
  2. 메소드 이름으로 쿼리 생성   (메서드 이름에 파라매터 많아지면 지저분)
  3. 메소드 이름으로 JPA NamedQuery 호출

 

 

 

1. @Query, 리포지토리 메소드에 쿼리 정의하기

//member repository
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);
}
  • @org.springframework.data.jpa.repository.Query 어노테이션을 사용
  • 실행할 메서드에 정적 쿼리를 직접 작성하므로 이름 없는 Named 쿼리라 할 수 있음
  • 복잡한 JPQL도 직접 써주니까 메서드 명이 간략
  • 애플리케이션 실행 시점에 문법 오류를 발견할 수 있음(매우 큰 장점!)
  • JPQL을 repo interface에 바로 적을 수 있음.

 

 

 

2. 메소드 이름으로 쿼리 생성

순수 JPA

// 순수 JPA repository
public List<Member> findByUsernameAndAgeGreaterThan(String username, int age) {
	return em.createQuery("select m from Member m where m.username = :username and m.age > :age")
    	.setParameter("username", username)
		.setParameter("age", age)
		.getResultList();
    }

 

스프링 데이터 JPA

// 스프링 데이터 JPA repository
public interface MemberRepository extends JpaRepository<Member, Long> {  // <entity, id type>
	List<Member> findByUsernameAndAgeGreaterThan(String username, int age);
}

테스트 코드는 동일 

// 순수 JPA 테스트코드
@Test
public void findByUsernameAndAgeGreaterThan() {
	Member m1 = new Member("AAA", 10);
	Member m2 = new Member("AAA", 20);
	memberJpaRepository.save(m1);
	memberJpaRepository.save(m2);
        
	List<Member> result = memberJpaRepository.findByUsernameAndAgeGreaterThan("AAA", 15);
	assertThat(result.get(0).getUsername()).isEqualTo("AAA");
	assertThat(result.get(0).getAge()).isEqualTo(20);
	assertThat(result.size()).isEqualTo(1);
}
  • find_ _ _By : _ _ _쓰는 것은 선택이며 내가 이 메서드가 뭔지 알 수 있도록 도와주는 역할 (jpa는 모름)
  • 쿼리 메소드 필터 조건 :  https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation (스프링 데이터 JPA 공식 문서 참고)
  • 이 기능은 엔티티의 필드명이 변경되면 인터페이스에 정의한 메서드 이름도 꼭 함께 변경해야 함. 그렇지 않으면 애플리케이션을 시작하는 시점에 오류가 발생. (이렇게 애플리케이션 로딩 시점에 오류를 인지할 수 있는 것이 스프링 데이터 JPA의 매우 큰 장점)
  • 실무에서는 메소드 이름으로 쿼리 생성 기능은 파라미터가 증가하면 메서드 이름이 매우 지저분해진다. 따라서 @Query 기능을 자주 사용하게 된다.

 

 

3. JPA NamedQuery

엔티티 위에 NamedQuery를 생성해두면

// entity
@Entity
@NamedQuery(
	name="Member.findByUsername",
	query="select m from Member m where m.username = :username")
public class Member {
 	...
}

 

1. 스프링 데이터 JPA로 NamedQuery를 사용하는 방법과 

// member repository
@Query(name = "Member.findByUsername")
List<Member> findByUsername(@Param("username") String username);

 

2. 스프링 데이터 JPA로 Named 쿼리 호출하는 방법이 있다.

// member repository
public interface MemberRepository extends JpaRepository<Member, Long> { //** 여기 선언한 Member 도메인 클래스
	List<Member> findByUsername(@Param("username") String username);
}
  • @Query 를 생략하고 메서드 이름만으로 Named 쿼리를 호출할 수 있다. 
  • 애플리케이션 실행 시점에 문법 오류를 발견할 수 있음(매우 큰 장점!)