@Query
는 JPQL 문법을 문자열로 입력하기 때문에, 컴파일 시점에 에러가 발견되지 않는다.Querydsl
를 알아보자.@Query("select i from Item wheere ...)
위 코드의 JPQL의 문법 중 where를 wheere로 잘못 입력되었다.
이때 Querydsl이 오타 발생시 바로 알려주고, 동적으로 쿼리를 생성해준다!
@PersistenceContext
EntityManager em;
@Test
@DisplayName("Querydsl 조회 테스트1")
public void queryDslTest(){
this.createItemList();
JPAQueryFactory queryFactory = new JPAQueryFactory(em); // 쿼리를 동적으로 생성
QItem qItem = QItem.item; // 쿼리 생성위해 자동생성된 QItem 객체 사용
JPAQuery<Item> query = queryFactory.selectFrom(qItem)
.where(qItem.itemSellStatus.eq(ItemSellStatus.SELL))
.where(qItem.itemDetail.like("%" + "테스트 상품 상세 설명" + "%"))
.orderBy(qItem.price.desc());
List<Item> itemList = query.fetch(); // 쿼리 결과를 리스트로 반환, fetch(0 시점에 쿼리문 실행
for(Item item : itemList){
System.out.println(item.toString());
}
}
@PersistenceContext
: 영속컨텍스트 사용하기 위해 EntityManager 빈을 주입QItem
: QueryDSL전용 엔티티 (간단한 쿼리는 (Spring Data)JPA를 사용하고, 동적쿼리는 QueryDSL을 사용하여 개발하곤 합니다.)메소드 | 내용 |
---|---|
List<T> fetch() | 조회 결과 리스트 반환 |
T fetchOne | 조회 대상이 1건인 경우 제네릭으로 지정한 타입 반환 |
T fetchFirst() | 조회 대상 중 1건만 반환 |
Long fatchCount() | 조회 대상 개수 반환 |
QueryResult<T> fetchResults() | 조회한 리스트와 전체 개수를 포함한 QueryResults 반환 |
Hibernate:
select
item0_.item_id as item_id1_0_,
item0_.item_detail as item_det2_0_,
item0_.item_nm as item_nm3_0_,
item0_.item_sell_status as item_sel4_0_,
item0_.price as price5_0_,
item0_.rec_time as reg_time6_0_,
item0_.stock_number as stock_nu7_0_,
item0_.update_time as update_t8_0_,
from
item item0_
where
item0_.item_sell_status=?
and(
item-_.item_detail like ? escape '!'
)
order by
item0_.price desc
QuerydslPredicateExecutor를 이용한 상품 조회를 해보자
Predicate란?
'이 조건이 맞다'고 판단하는 근거를 함수로 제공하는 것
public interface ItemRepository extends JpaRepository<Item, Long>,
QuerydslPredicateExecutor<Item> {
메소드 | 내용 |
---|---|
long count(Predicate) | 조건에 맞는 데이터 총 개수 반환 |
boolean exists(Predicate) | 조건에 맞는 데이터 존재 여부 반환 |
Iterator findAll(Predicate) | 조건에 맞는 모든 데이터 반환 |
Page<T> findAll(Predicate, Pageable) | 조건에 맞는 페이지 데이터 반환 |
Iterator findAll(Predicate, Sort) | 조건에 맞는 정렬된 데이터 반환 |
T findOne(Predicate) | 조건에 맞는 데이터 1개 반환 |
public void createItemList2(){
for(int i=1;i<=5;i++){
Item item = new Item();
item.setItemNm("테스트 상품"+i);
item.setPrice(10000 + i);
item.setItemDetail("테스트 상품 상세 설명"+i);
item.setItemSellStatus(ItemSellStatus.SELL);
item.setStockNumber(100);
item.setRegTime(LocalDateTime.now());
item.setUpdateTime(LocalDateTime.now());
itemRepository.save(item);
}
for(int i=6;i<=10;i++){
Item item = new Item();
item.setItemNm("테스트 상품"+i);
item.setPrice(10000 + i);
item.setItemDetail("테스트 상품 상세 설명"+i);
item.setItemSellStatus(ItemSellStatus.SOLD_OUT);
item.setStockNumber(0);
item.setRegTime(LocalDateTime.now());
item.setUpdateTime(LocalDateTime.now());
itemRepository.save(item);
}
}
@Test
@DisplayName("상품 Querydsl 조회 테스트2")
public void queryDslTest2(){
this.createItemList2();
BooleanBuilder booleanBuilder = new BooleanBuilder(); // 2: 쿼리에 들어갈 조건을 만들어주는 빌더
QItem item = QItem.item;
String itemDetail = "테스트 상품 상세 설명";
int price = 10003;
String itemSellStat = "SELL";
booleanBuilder.and(item.itemDetail.like("%" + itemDetail + "%")); // 3: 조회 시 조건
booleanBuilder.and(item.price.gt(price));
if(StringUtils.equals(itemSellStat, ItemSellStatus.SELL)){
booleanBuilder.and(item.itemSellStatus.eq(ItemSellStatus.SELL));
}
Pageable pageable = PageRequest.of(0, 5); // 4: 데이터를 페이징해 조회하도록 Pageble 객체 생성
Page<Item> itemPagingResult =
itemRepository.findAll(booleanBuilder, pageable); // 5: 조건에 맞는 데이터를 Page 객체로 받아옴.
System.out.println("total elements : " +
itemPagingResult. getTotalElements());
List<Item> resultItemList = itemPagingResult.getContent();
for(Item resultItem: resultItemList){
System.out.println(resultItem.toString());
}
}
createItemList2
: 1~10까진 SELL, 11~20까진 SOLDOUTBooleanBuilder
: 동적으로 쿼리를 생성해주면서 조건까지 넣을 꺼임.and
: 조회 시 사용할 조건들을 설정Pageable
: 페이지를 어떻게 보여줄지 정보를 전달하는 APIPageRequest
: 몇 페이지, 한 페이지의 사이즈, Sorting 방법(Option)을 가지고, Repository에 Paging을 요청할 때 사용하는 것Hibernate:
select
item0_.item_id as item_id1_0_,
item0_.item_detail as item_det2_0_,
item0_.item_nm as item_nm3_0_,
item0_.item_sell_status as item_sel4_0_,
item0_.price as price5_0_,
item0_.rec_time as reg_time6_0_,
item0_.stock_number as stock_nu7_0_,
item0_.update_time as update_t8_0_,
from
item item0_
where
(
item0_.item_detail like ? escape '!'
)
and item0_.price>?
and item0_.item_sell_status=? limit ?