@QueryProjection
- 상품 조회시 DTO 객체로 결곽밧을 받는 방법
- Item 객체로 값을 받은 후 DTO 클래스로 변환하는 과정 없이 바로 DTO객체를 뽑아낼수 있다.
1) DTO 생성
package com.shop.dto;
import com.querydsl.core.annotations.QueryProjection;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class MainItemDto {
private Long id;
private String itemNm;
private String itemDetail;
private String imgUrl;
private Integer price;
@QueryProjection
public MainItemDto(Long id, String itemNm, String itemDetail, String imgUrl, Integer price){
this.id = id;
this.itemNm = itemNm;
this.itemDetail = itemDetail;
this.imgUrl = imgUrl;
this.price = price;
}
}
2) 컴파일
3) 인터페이스 메소드 생성
package com.shop.repository;
import com.shop.dto.ItemSearchDto;
import com.shop.dto.MainItemDto;
import com.shop.entity.Item;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
public interface ItemRepositoryCustom {
...
Page<MainItemDto> getMainItemPage(ItemSearchDto itemSearchDto, Pageable pageable);
}
4) 인터페이스 구현
- selectForm 에서 select 로 변경되었고 select() 메소드안에 매개변수 형태도 달라졌다.
package com.shop.repository;
import com.querydsl.core.QueryResults;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.shop.constant.ItemSellStatus;
import com.shop.dto.ItemSearchDto;
import com.shop.dto.MainItemDto;
import com.shop.dto.QMainItemDto;
import com.shop.entity.Item;
import com.shop.entity.ItemImg;
import com.shop.entity.QItem;
import com.shop.entity.QItemImg;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.support.PageableExecutionUtils;
import org.thymeleaf.util.StringUtils;
import javax.persistence.EntityManager;
import java.time.LocalDateTime;
import java.util.List;
public class ItemRepositoryCustomImpl implements ItemRepositoryCustom{
private JPAQueryFactory queryFactory;
...
public BooleanExpression itemNmLike(String searchQuery){
return StringUtils.isEmpty(searchQuery) ? null : QItem.item.itemNm.like("%"+searchQuery+"%");
}
@Override
public Page<MainItemDto> getMainItemPage(ItemSearchDto itemSearchDto, Pageable pageable) {
QItem item = QItem.item;
QItemImg itemImg = QItemImg.itemImg;
List<MainItemDto> fetch = queryFactory
.select(new QMainItemDto(
item.id,
item.itemNm,
item.itemDetail,
itemImg.imgUrl,
item.price
))
.from(itemImg)
.join(itemImg.item, item)
.where(itemImg.repimgYn.eq("Y"))
.where(itemNmLike(itemSearchDto.getSearchQuery()))
.orderBy(item.id.desc())
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();
JPAQuery<MainItemDto> count = queryFactory
.select(new QMainItemDto(
item.id,
item.itemNm,
item.itemDetail,
itemImg.imgUrl,
item.price
))
.from(itemImg)
.join(itemImg.item, item)
.where(itemImg.repimgYn.eq("Y"))
.where(itemNmLike(itemSearchDto.getSearchQuery()));
return PageableExecutionUtils.getPage(fetch, pageable, ()-> count.fetch().size());
}
}
5) 서비스 구현
package com.shop.service;
import com.shop.dto.ItemFormDto;
import com.shop.dto.ItemImgDto;
import com.shop.dto.ItemSearchDto;
import com.shop.dto.MainItemDto;
import com.shop.entity.Item;
import com.shop.entity.ItemImg;
import com.shop.repository.ItemImgRepository;
import com.shop.repository.ItemRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.multipart.MultipartFile;
import javax.persistence.EntityNotFoundException;
import java.util.ArrayList;
import java.util.List;
@Service
@Transactional
@RequiredArgsConstructor
public class ItemService {
private final ItemRepository itemRepository;
private final ItemImgService itemImgService;
private final ItemImgRepository itemImgRepository;
...
@Transactional(readOnly = true)
public Page<MainItemDto> getMainItemPgae(ItemSearchDto itemSearchDto, Pageable pageable){
return itemRepository.getMainItemPage(itemSearchDto, pageable);
}
}
6) 컨트롤러 작성
package com.shop.controller;
import com.shop.dto.ItemSearchDto;
import com.shop.dto.MainItemDto;
import com.shop.service.ItemService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.Optional;
@Controller
@RequiredArgsConstructor
public class MainController {
private final ItemService itemService;
@GetMapping(value = "/")
public String main(ItemSearchDto itemSearchDto, Optional<Integer> page, Model model){
Pageable pageable = PageRequest.of(page.isPresent() ? page.get() : 0, 6);
Page<MainItemDto> items = itemService.getMainItemPgae(itemSearchDto, pageable);
model.addAttribute("items", items);
model.addAttribute("itemSearchDto", itemSearchDto);
model.addAttribute("maxPage", 5);
return "main";
}
}
7) main.html 작성
소스길어서 아래링크 참고
https://github.com/gusrl6394/SpringbootShop/blob/master/src/main/resources/templates/main.html
결과)
반응형