Spring Boot - @Query

김명식·2023년 5월 4일
0
post-thumbnail

@Query

앞선 포스팅에서 설명했듯이,
Query Method는 간단한 쿼리를 처리할 수 있지만
조건이 많아질 때 이름이 너무 길어져 오히려 이해하기 어려운 상황이 발생한다.

이러한 경우에 사용하는 방법 중 하나가 바로 @Query 어노테이션이다.
@Query 어노테이션을 사용하면
SQL과 유사한 JPQL 이라는 객체지향 쿼리 언어를 통해 복잡한 쿼리도 처리가 가능하다.


JPQL ?

JPQL은 객체지향 쿼리 언어로 객체 모델과 관련된 데이터를 검색하고 조작하는데 사용된다.
JPQL은 SQL과 비슷한 구문을 가지고 있지만, 한가지 큰 차이점 이 있다.

SQL은 데이터베이스 테이블을 대상으로 하지만
JPQL은 엔티티 객체를 대상으로 작업한다.

또한, JPQL은 SQL을 추상화해서 사용하기 때문에 특정 데이터베이스 SQL에 의존하지 않는다.
이러한 특징으로 인해 쿼리를 JPQL로 작성했다면 프로젝트 중간에 데이터베이스를 변경해도 애플리케이션이 영향을 받지 않는다.


// @JPQL 작성법

@Query("select i " + 
		"from Item i " + 
        "where i.itemName like %:itemName% + "
        "order by i.price desc ")
List<Item> findByItemName(@Param("itemName") String itemName);        

위 JPQL로 작성된 쿼리는 from 뒤에 Entity 클래스로 작성한 Item을 지정해 주었고,
Item으로부터 데이터를 Select 하겠다는 것을 의미한다.

기존의 SQL과 굉장히 유사한 문법이다.


JPQL을 작성할 때 주의할 점이 두 개 있다.

  1. @Query 어노테이션을 사용하면 함수의 인자에 @Param 을 꼭 붙여줘야한다.
    @Param 인자 == %:itemName%
  2. @JPQL을 작성 중 개행할 때 반드시 " " 공백을 넣어놓고 개행.
    만약 아래와 같이 쿼리를 쓴다면
    @Query("select i" + 
    		"from Item i" + 
          	"where ...."
    Jave는 이를 아래와 같이 연속된 문자열로 인식하기 때문에 오류가 발생 한다.
    select ifrom Item iwhere ...

@Query JPQL을 사용한 메서드의 테스트코드를 작성해보자.

Entity -

@Entity
@Table(name="item")
@Getter
@Setter
@ToString
public class Item {
        
		@Id
		@GeneratedValue(strategy = GenerationType.AUTO)
		private Long id;
		
		private String itemName; // 상품명
		private int price; // 가격

}
Repository - 

@Query("select i " + 
		"from Item i " + 
        "where i.itemName like %:itemName% + "
        "order by i.price desc ")
List<Item> findByItemName(@Param("itemName") String itemName);     
}
TestCode - 

@SpringBootTest
class ItemRepositoryTest {

	// 의존성 주입
	@Autowired
	ItemRepository itemRepository;

	@Test
	@DisplayName("상품명 조회 테스트") 
	public void JpqlQueryTest() {

		// 테스트용
		Item item = new Item();
		item.setItemName("테스트아이템");
		item.setPrice(100);

		// DB에 저장
		itemRepository.save(item);
		
		// 조회
		List<Item> itemList = itemRepository.findByItemName("테스트아이템");

		for (Item item : itemList) {

			System.out.println(item.toString());

		}

	}

}
테스트 결과 - 
Item
(id=1, 
ItemName=테스트아이템, 
price=100,
)
profile
BackEnd & AWS Developer

0개의 댓글